# Sleep mode & resources
URL: https://openship.io/docs/guides/sleep-mode-resources.md

Set optional container resource limits and choose whether your app sleeps when idle or stays on.

import { Step, Steps } from 'fumadocs-ui/components/steps';

Projects share their server's available CPU and memory by default. You can add container limits
to control how much an individual app can use, and choose whether it sleeps when idle or stays on.
These settings do not change your code or resize the server. On Openship Cloud, the subscription
sets the server's purchased capacity separately.

<Callout title="What you need first">
- A project you've already deployed (see [Your first deployment](/docs/getting-started/first-deployment) if not).
- For the CLI examples, the `openship` command installed and logged in.
- The **project ID** for the CLI/API bits. Run `openship project list` to find it.
</Callout>

## The two settings, in plain words

- **Resources** — optional ceilings on the **vCPU** (processing power) and **RAM** (working memory)
  an app can use within its server. **Full capacity** adds no container cap; other projects share
  the available capacity. Server storage and paid capacity are managed separately.
- **Sleep mode** — what happens when your app is idle:
  - **Auto Sleep** (the default) — the app stops when no one is using it and wakes up on the next request.
    Cheaper to run, and Openship wakes it instantly, so visitors don't wait.
  - **Always On** — the app never stops. Highest availability, but it's running (and costing) around the clock.

<Callout title="Which sleep mode should I pick?" type="info">
Start with **Auto Sleep**. It's the recommended default and right for the large majority of apps. Switch to
**Always On** only if you have a specific reason — for example a background job that must keep running, or an
app that can't tolerate the brief wake-up on the very first request after a quiet spell.
</Callout>

## Set resources

Optional container limits live below the server selector in **Machine Power** on the deployment
settings page. Existing projects also expose Machine Power in their settings. The API uses the
same values. The Cloud subscription controls the server's capacity separately.

<Callout title="Full capacity by default" type="info">
Connected and managed servers default to **Full capacity**: a container uses the server's available
CPU and RAM, shared with its other projects. Select a preset or **Custom** only when you need an
additional per-container limit. Choosing a limit does not change the server's plan or disk size.

Builds also have no additional CPU or memory limits unless you configure them.
Cloud admission prevents an uncapped build from overlapping another build on the same
server; configured build limits can share capacity. Builds do not provision a second VM.
</Callout>

<Tabs items={['Deploy wizard (Cloud)', 'Project settings', 'API']}>

<Tab value="Deploy wizard (Cloud)">

<Steps>

<Step>

### Start a deploy and choose Openship Cloud

Begin a deployment as usual. When you reach the "Where do you want to deploy?" choice, pick **Openship
Cloud**. Select your server; runtime and **Machine Power** settings appear below it, with a preview
and **Continue** on the right.

</Step>

<Step>

### Keep full capacity or add a limit

**Full capacity** is selected by default. Choose **Customized** beside it to reveal the
presets and custom limits. Pick a preset or save custom values before continuing; the
choices stay visible. Selecting **Full capacity** again clears the limits and hides them:

| Limit | vCPU | RAM |
|---|---|---|
| **Micro** | 0.25 | 256 MB |
| **Low** | 0.5 | 512 MB |
| **Medium** | 1 | 1 GB |
| **High** | 2 | 2 GB |
| **Extra large** | 4 | 8 GB |

**Custom** edits CPU and RAM inline. Enter `0` in a dimension to leave it uncapped; Save applies
the choice and Cancel retains the previous selection. Positive limits must fit the selected server.

</Step>

<Step>

### Deploy

Continue to the app configuration, then deploy. Any selected container limits apply when it starts.

</Step>

</Steps>

</Tab>

<Tab value="Project settings">

Any existing project has a **Machine Power** card. On a single app it's under
**Configuration**; on a multi-service (compose) project it's on the **Services** tab, since that
project shape has no single-app Configuration.

The card shows the target machine's detected capacity in its header, and offers:

- **Full capacity** — the default on connected and managed servers. The container shares the host’s available capacity.
- **Micro / Low / Medium / High / Extra large** — the same presets Openship Cloud offers. A preset larger than the
  machine is greyed out rather than silently unhonored.
- **Custom** — type your own vCPU and MB. `0` in either field means no limit for that dimension, so
  you can cap memory while leaving CPU free.

Limits apply when the container is **recreated**, so redeploy for a change to take effect. The card
says so inline. Every deploy also logs the limits it applied (`Resource limits: 2 vCPU · 4 GB`, or
`no limits (machine capacity)`), so a cap is never invisible.

A service in a compose project can override the project value for itself — see
[per-service limits](#per-service-limits-compose).

</Tab>

<Tab value="API">

Update an existing project's resources with a `PATCH` to its resources endpoint. All paths are under `/api`
on your instance (for example `https://your-host/api/...`). Authenticate with a personal access token in the
`Authorization` header — create one from **Settings → Tokens** or with `openship token create`. See
[Authentication](/docs/security/auth) for the full token model.

You can set **production** resources for your live app and **build** resources for compilation.
Sizes are given as `cpuCores`, `memoryMb`, and `diskMb`. On Openship Cloud, build CPU/RAM
are optional upper limits. Only configured values become Docker limits; omitted or zero
dimensions remain uncapped. Send `{"build": null}` to remove the additional build limits. A saved build cap does not change production resources.

```bash
curl -X PATCH https://your-host/api/projects/PROJECT_ID/resources \
  -H "Authorization: Bearer $OPENSHIP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "production": { "cpuCores": 1, "memoryMb": 1024, "diskMb": 16384 },
    "build":      { "cpuCores": 2, "memoryMb": 2048, "diskMb": 16384 }
  }'
```

You can also send `{"tier": "medium"}` instead of explicit numbers, or `{"tier": "unlimited"}`
to remove the caps on either server type.

`0` means **no limit**. A non-zero `cpuCores` must be at least 0.25 and `memoryMb` at least 128; the
UPPER bound is the target machine's own capacity, not a fixed number — so a large self-hosted box is
usable in full. Managed server storage is controlled by its subscription, not the project's
`diskMb` field. Resource fields are optional; omitted dimensions have no additional container cap.

`GET /api/projects/PROJECT_ID/resources` reads the current values, and also reports the detected
machine `capacity` when available, plus `requiresLimit: false` for connected and managed hosts.
Openship Cloud also returns `buildMode`: `automatic` or `custom`. In automatic mode, the
returned build CPU/RAM values are zero and Docker receives no additional build limits.
Cloud reservation accounting stays separate from those container settings.

</Tab>

</Tabs>

## Per-service limits (compose)

In a multi-service project the project-wide value applies to **each** service container — it's a
per-container cap, not a budget split across them.

A single service can override it. Openship reads a compose file's own limits, in either spelling, and
applies them over the project value **field by field** — so a service that declares only memory keeps
the project's CPU setting:

```yaml
services:
  api:
    image: my/api
    mem_limit: 4g          # short form
    cpus: 2
  worker:
    image: my/worker
    deploy:                # swarm form — also honored
      resources:
        limits:
          memory: 8G
          cpus: "1.5"
```

The same override is available declaratively in `openship.json` under
[`services[].resources`](/docs/reference/openship-json#services-compose).

<Callout title="Adopted containers keep their limits" type="info">
Importing an existing Docker container reads the caps it's actually running with — including one you
applied by hand with `docker update --memory` — so adoption doesn't quietly reset them.
</Callout>

## Set sleep mode

Sleep mode has two values: `auto_sleep` (the default) and `always_on`. Set it from the CLI or the API.

<Tabs items={['CLI', 'API']}>

<Tab value="CLI">

```bash
# Let the app sleep when idle (the default, cheapest)
openship project sleep-mode PROJECT_ID auto_sleep

# Keep it running around the clock
openship project sleep-mode PROJECT_ID always_on
```

Don't know your project ID? `openship project list` shows every project with its ID.

</Tab>

<Tab value="API">

```bash
curl -X POST https://your-host/api/projects/PROJECT_ID/sleep-mode \
  -H "Authorization: Bearer $OPENSHIP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "sleep_mode": "always_on" }'
```

`sleep_mode` must be `auto_sleep` or `always_on`. (You can also change it alongside resources by sending a
`sleepMode` field to `PATCH /api/projects/PROJECT_ID/resources`.)

</Tab>

</Tabs>

<Callout title="Sleep mode is about a running server" type="info">
Sleep mode matters for apps with a running process (a server or API). A purely static site has nothing to put
to sleep — it's just files being served — so the setting has no visible effect there.
</Callout>

## Troubleshooting

<Callout title="A resource value is rejected" type="error">
A cap larger than the target machine is refused with the real numbers, e.g.
`Memory limit 8192 MB exceeds the machine's 2048 MB`. Lower the value, or use `0` / the `unlimited`
tier to remove the cap. A non-zero value below the workable floor is refused too (`at least 0.25
cores`, `at least 128 MB`). If Openship couldn't reach the machine to read its capacity, no ceiling is
enforced at all — the value you send is accepted as-is.
</Callout>

<Callout title="Sleep mode command is rejected" type="warn">
The mode must be exactly `auto_sleep` or `always_on` — nothing else. Check the spelling (both use an
underscore), and make sure the project ID is right. `openship project list` confirms both.
</Callout>

<Callout title="I made it Always On but costs went up" type="info">
That's expected — **Always On** keeps the machine running 24/7. If you don't need constant availability,
switch back with `openship project sleep-mode PROJECT_ID auto_sleep` and the app will sleep when idle again.
</Callout>

## Related guides

<Cards>
  <Card title="Deploy to your own server" href="/docs/guides/custom-servers" description="Run your app on a machine you control instead of Openship Cloud." />
  <Card title="Logs & monitoring" href="/docs/guides/logs-monitoring" description="Watch how your app behaves so you know when to size it up or down." />
  <Card title="Rollback & redeploy" href="/docs/guides/rollback-redeploy" description="Ship a new version, or go back to a working one, in seconds." />
</Cards>
