# Lifecycle and sleep

URL: https://briq.cloud/docs/concepts/lifecycle-and-sleep

> States, moves, and the one setting that decides when a briq stops on its own.

## States

```text
creating → running → stopping → stopped → starting → running
running → stopping → sleeping → starting → running
stopped by a limit → sleeping, once the limit clears
any live state → destroying → destroyed
a failed move → error
```

| State                     | Meaning                                                                                                                                                                                                                                  | Billed |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ |
| `creating`                | Image pulling, healthcheck pending                                                                                                                                                                                                       | No     |
| `running`                 | Healthcheck passed, or the process is up                                                                                                                                                                                                 | Yes    |
| `stopping`                | Stop on its way                                                                                                                                                                                                                          | Yes    |
| `sleeping`                | Machine stopped, disk kept. The next call or visit wakes it                                                                                                                                                                              | No     |
| `stopped`                 | Machine stopped, disk kept: by `briq_stop`, by its process exiting, or by a limit not yet cleared. See [Other stops](#other-stops)                                                                                                       | No     |
| `starting`                | Start on its way                                                                                                                                                                                                                         | No     |
| `destroying`, `destroyed` | Machine and disk removed                                                                                                                                                                                                                 | No     |
| `error`                   | The create failed: an image, a healthcheck that never passed, a process that exited before it was ready, or the infrastructure. Reason in `error`. Destroyed automatically after 7 days (`destroysAt`); its logs are readable until then | No     |

`briq_stop`, `briq_start` and `briq_destroy` return once the move lands (up to 30 seconds), or with
the pending state. They are safe to repeat: stopping a stopped briq returns its state, and asking
again while a move is in flight waits for it. A destroy overtakes any move in flight. Impossible
moves, like starting a destroyed briq, return `invalid_state` (409).

Moves run in the background: if your client disconnects, the briq is still tracked, still put to
sleep on time, and the move completes.

## Sleep

Every briq has one setting that decides when it stops on its own: `sleep`. After that long without
use, the briq goes to sleep. A sleeping briq keeps its disk and is not billed for compute, and the
next use wakes it.

| `sleep`                        | The briq                                                                                                 |
| ------------------------------ | -------------------------------------------------------------------------------------------------------- |
| `"1h"` (default on briq.cloud) | sleeps after 1 hour without use                                                                          |
| `"30m"`, `"3h"`, `"7d"`        | sleeps after that long without use: 5 minutes to 7 days                                                  |
| `"never"`                      | is always on: it runs until someone stops it, its process exits, or a limit stops it. Pro plan and above |

Nothing is deleted because of time. A sleeping briq is still there tomorrow and next month, with
its data, until you `briq_destroy` it.

### The `sleep` value

A string: a whole number and a unit (`m` for minutes, `h` for hours, `d` for days), or `"never"`.
Never a number. A call that sends one is refused, with the string to send instead:

```text
sleep must be a string: "30m", "3h", "7d" or "never". You sent 30, a number. For 30 minutes, pass "30m"
```

Responses show the shortest exact form: `"120m"` comes back as `"2h"`. Every response about a
running briq carries `sleepsAt`, the time it goes to sleep unless it is used before then. Every
use moves it later, so read it as a time, not a deadline. It is `null` while the briq is not
running, and for an always-on briq.

### What counts as use

* Your calls on any briq of its stack: `briq_exec`, the file tools, `briq_logs`, `briq_expose`.
  Working on an app is using the database behind it too.
* Requests to the URL of any briq in its stack. A request to a [private URL](https://briq.cloud/docs/guides/expose-a-preview-url)
  counts only when it carries the URL's token.
* On the dashboard, running a command. Watching a briq's page or its logs does not count.

Work that happens only inside the briq is not seen: a long job, a worker reading a queue, a bot
that only opens outgoing connections. Give such a briq a `sleep` longer than that work, or
`"never"`.

### Waking up

The next call that needs the briq running (an exec, a file read or write, an expose) wakes it
first, and the sleeping briqs of its stack with it, each under the agent's own limits (a sibling
past them stays asleep). The agent sees a slower call, not an error. A
visit to its URL wakes the whole stack and waits for it. `nano` and `small` resume from a memory
snapshot in about a second; larger sizes start from scratch, and the first visitor waits a few
seconds.

### Changing it

Pass `sleep` to `briq_run` (with a recipe, every briq it makes gets the same), to `briq_fork`, or
call `briq_set_sleep` on an existing briq:

```text
briq_set_sleep({ briq: "bq_7kq2m9x1p4ab", sleep: "3h" })
briq_set_sleep({ briq: "bq_7kq2m9x1p4ab", sleep: "1d", stack: true })
```

A running briq sleeps the new window from now. A sleeping briq stays asleep: the window applies
from its next wake. With `stack: true`, every briq of its stack gets the same.

### Limits

A window must be one the environment and the agent's key allow:

* The longest window is 7 days on briq.cloud.
* A key can set a shorter longest window (`maxSleep`, see [Keys and policy](https://briq.cloud/docs/concepts/keys-and-policy)).
* `"never"` needs the Pro plan or above. A team that moves down keeps the always-on briqs it has;
  only new ones are refused.

A longer window is refused, never shortened behind your back, and the error says what to send:

```text
this fork would sleep after "3d", longer than this key allows ("1d"); pass sleep: "1d" or shorter
```

A fork keeps its source's `sleep` unless you pass one, so a fork made by a key with a shorter
longest window is refused the same way.

### Example: a site that stays reachable for a month

```text
briq_run({ recipe: "node", params: { files: … }, expose: "public", sleep: "30m" })
```

With no visits for 30 minutes it sleeps, and the next visit wakes it. It costs nothing while it
sleeps, and stays reachable for as long as you keep it.

## Other stops

A briq also stops when:

| `stoppedReason` | What stopped it                                                     | What brings it back                                                                   |
| --------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| `cap`           | Its key's daily spend cap                                           | From the next UTC day, or once the cap is raised, it is asleep: the next use wakes it |
| `credits`       | The team ran out of credits                                         | Once the team tops up (or pays as it goes), it is asleep: the next use wakes it       |
| `user`          | `briq_stop`, also on a sleeping briq: visits then no longer wake it | `briq_start`                                                                          |
| `exited`        | Its own process ending                                              | `briq_start` (see below)                                                              |

Until then, a call that needs the briq running fails: `quota_exceeded` (402) for the cap,
`payment_required` (402) for credits, `invalid_state` (409) after a stop or an exit. Its URL
answers 503. A briq the provider stopped on its own (`provider`) is asleep, like an unused one.

The spend cap and the credits are what bound a briq in use: a briq is never stopped while it is
in use because a timer ran out. Briqs made from the dashboard have a daily cap too.

## When the process exits

A briq runs one long-lived process: the image's command, or your `cmd`. When it exits (a crash, a
missing file, a command that simply finishes), the briq stops with `stoppedReason: "exited"`; a
process that failed (a non-zero exit code) is first restarted up to three times. Its status carries `lastExit`: the exit code, the
time, and whether it ran out of memory. `briq_logs` shows what it printed.

An exited briq does not come back on the next call or visit, since that would only repeat the
exit: calls return `invalid_state` with the exit code. `briq_start` runs the same command and files
again, which is right when the cause was outside it (a dependency that was down, a spike that ran
it out of memory). A briq's command, files and size cannot be changed in place: to change them,
run a new briq with the fix and `briq_destroy` this one. The usual cause is a command that needs
files the briq does not have, such as your app's code: pass those in the spec's
[`files`](https://briq.cloud/docs/concepts/briq#files), written before the process starts.

A process that exits before the briq is ready (before its healthcheck passes) fails the create
instead: the briq is in `error`, and `error` says how the process exited.

A process that is still up when its healthcheck's `timeoutMs` runs out is a slow boot, not a
failure: the briq stays `creating` and the create waits for the healthcheck again, up to three
times in all. Meanwhile `error` says it is still starting. Only then does the create fail.

## A long time awake

A briq awake for 7 days in a row is marked in `briq_list` and on the dashboard ("awake for 8
days"). It is always on, or something keeps using it: often an uptime check or a crawler on a
public URL. It changes nothing about the briq; it is there so that a briq nobody is watching does
not run unseen.

## Forks

[`briq_fork`](https://briq.cloud/docs/concepts/fork) creates a new briq from a copy of a running, sleeping or stopped
briq's volume, with its own lifecycle. A briq mid-move cannot be forked until the move lands.
