> Fetch the index of every Tonbo docs page as Markdown at https://tonbo.dev/llms.txt

# Rules: keep state

Last updated 2 November 2026

> Machines are not open yet. These pages describe Machines as they will open; until then, a create answers [`region_not_offered`](https://tonbo.dev/docs/machines/troubleshooting/manage.md#region_not_offered) (422), “Machines are not offered in any region yet.”

Check these rules before you rely on what your Machine keeps: each keeps its data safe across a sleep, a wake or a crash.

The examples use the database a Machine opens as [Keep data in its database and Volume](https://tonbo.dev/docs/machines/database.md#open) shows, and a `node:http` server.

### Keep what must last in its database or on its Volume

Every wake starts your image on fresh disks with empty memory, and only the database and the Machine’s Volume keep data durably. On the Volume, a file is durable once a flush such as `fsync` returns; `close` alone is not one (see [Sleep guarantees](https://tonbo.dev/docs/machines/guarantees/sleep.md)).

**Do**

```js
db.prepare("INSERT INTO notes(id, body) VALUES (?, ?)").run(id, body);
await db.synced();
```

**Don’t**

```js
writeFileSync(`/scratch/notes/${id}.json`, body); // gone at the next wake
```

### Reconnect, and read the clock again, after a wake

A wake is a new boot: every connection your program had is gone, and so is every timer it set (see [What a wake starts with](https://tonbo.dev/docs/machines/sleep.md#continue)).

**Do**

```js
async function call(body) {
  try {
    return await upstream.send(body);
  } catch {
    upstream = await connect(); // the connection did not survive the sleep
    return await upstream.send(body);
  }
}
```

**Don’t**

```js
const upstream = await connect(); // once, at start: fails after the next sleep
setTimeout(expireSessions, 60_000); // fires at once, or never, across a sleep
```

### Await synced() before you answer

A reply sent before `synced()` resolves can announce a commit that a crash then loses (see [Answer after synced()](https://tonbo.dev/docs/machines/database.md#answer-after-synced)).

**Do**

```js
db.prepare("INSERT INTO orders(id, item) VALUES (?, ?)").run(order.id, order.item);
await db.synced();
res.writeHead(201).end();
```

**Don’t**

```js
db.prepare("INSERT INTO orders(id, item) VALUES (?, ?)").run(order.id, order.item);
res.writeHead(201).end(); // the order is only on this Machine's disk
```

### Open the database with the settings the Machine gives you

The platform names the database and its cache directory, and its bound on what may wait keeps the backlog small enough to send before a sleep ends (see [Open it](https://tonbo.dev/docs/machines/database.md#open)).

**Do**

```js
import { open } from "@tonbo/sqlite-ursula";

// On a Machine the platform always sets these: the database, its cache
// directory and how much may wait to be sent. It also keeps the token that
// opens the database fresh.
const db = await open(process.env.TONBO_DATABASE_URL, {
  dir: process.env.TONBO_VFS_CACHE_DIR,
  maxPendingBytes: Number(process.env.TONBO_VFS_MAX_PENDING_BYTES),
});
```

**Don’t**

```js
import { open } from "@tonbo/sqlite-ursula";

// The default backlog can outgrow what a sleep sends in time.
const db = await open(process.env.TONBO_DATABASE_URL);
```

### Handle SIGTERM: sync and exit within the stop grace

Every sleep sends `SIGTERM` and stops the Machine its stop grace later, 10 seconds by default, whatever stop signal the image names (see [Stopping](https://tonbo.dev/docs/machines/sleep.md#stop)).

**Do**

```js
process.on("SIGTERM", async () => {
  server.close(); // take no new requests
  await db.synced(); // every commit is durable from here
  db.close();
  process.exit(0);
});
```

**Don’t**

```js
process.on("SIGTERM", () => {}); // stopped anyway when the grace ends
```

### Finish the work before you answer, or keep the request open while it runs

Only an open request keeps a Machine awake, so work left running after the answer stops at the next sleep (see [What keeps it awake](https://tonbo.dev/docs/machines/sleep.md#awake)).

**Do**

```js
const result = await runJob(job);
db.prepare("INSERT INTO results(id, body) VALUES (?, ?)").run(job.id, JSON.stringify(result));
await db.synced();
res.writeHead(200).end(JSON.stringify(result));
```

**Don’t**

```js
res.writeHead(202).end('{"state":"queued"}');
runJob(job); // nothing keeps the Machine awake for this
```
