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

# Rules: size and cost

Last updated 29 October 2026

Check these rules when you decide how your program commits: each keeps the bill small and every transaction within the limit.

The examples use the connection `open()` returns, a node:sqlite `DatabaseSync`, as [Connect](https://tonbo.dev/docs/databases/connect.md) opens it.

### Batch a step’s writes into one transaction

Every commit costs at least one write, however small, and waits its turn to reach Tonbo. Twenty rows committed one by one cost twenty writes; in one transaction they cost one (see [the worked example](https://tonbo.dev/docs/databases/pricing.md#batch-a-step)).

**Do**

```js
db.exec("BEGIN");
try {
  for (const event of step.events) insert.run(step.id, JSON.stringify(event));
  db.exec("COMMIT"); // one commit, one write
} catch (error) {
  if (db.isTransaction) db.exec("ROLLBACK");
  throw error;
}
```

**Don’t**

```js
for (const event of step.events) insert.run(step.id, JSON.stringify(event)); // a commit per row
```

### Write what changed, not the whole state

A commit costs one write per 10 KiB of the pages it changes, so rewriting a large value every step costs many writes where a new row costs one (see [the worked example](https://tonbo.dev/docs/databases/pricing.md#write-what-changed)).

**Do**

```js
db.prepare("INSERT INTO messages(conversation, body) VALUES (?, ?)")
  .run(id, JSON.stringify(message));
```

**Don’t**

```js
conversation.messages.push(message);
db.prepare("UPDATE conversations SET body = ? WHERE id = ?")
  .run(JSON.stringify(conversation), id); // the whole conversation, every turn
```

### Keep each transaction under 128 MiB

A transaction over 128 MiB of changed pages fails with `too_large` and commits nothing (see [Limits](https://tonbo.dev/docs/databases/limits.md#transaction)). Load large data in batches.

**Do**

```js
for (let at = 0; at < rows.length; at += 1000) {
  db.exec("BEGIN");
  for (const row of rows.slice(at, at + 1000)) insert.run(row.id, row.body);
  db.exec("COMMIT");
}
```

**Don’t**

```js
db.exec("BEGIN");
for (const row of rows) insert.run(row.id, row.body); // millions of rows
db.exec("COMMIT"); // fails with too_large and commits nothing
```
