# Why AI Agents Make Me Reach for SQLite

> Source: <https://dev.to/gyu07/why-ai-agents-make-me-reach-for-sqlite-4dh0>
> Published: 2026-06-17 03:34:20+00:00

Lately I keep reaching for SQLite where, before, I'd have reached for Postgres without thinking.

It started with small services, then a bigger question: could a multi-tenant SaaS actually run on SQLite? And for AI agents specifically, isn't a local, embedded database the more natural home for their state?

Turso is the version of this stack I've found most compelling so far, especially when paired with Cloudflare. I wish D1 would reach embedded-replica parity with Turso, and that AWS offered a managed SQLite-style service the way it offers RDS for Postgres.

This isn't a "Postgres is over" argument. I still use Postgres more often than SQLite. And it isn't advice. It's just where my thinking has drifted recently — written down mostly so I can find out where it's wrong. Read it as one person's notes, not a recommendation.

Where I've landed for now (and expect to keep revising):

- SQLite isn't replacing Postgres.
- For
work state, it's increasingly my first reach, not my last.- AI agents push this harder: their state is high-churn, local, and mostly private.
- The answer isn't all-local. It's a local
workbenchplus a centralledger.

For years, "where does the data live?" had one practical answer: a server, behind an API, in a shared Postgres. A lot of that wasn't architecture — it was the cheapest shape available.

SQLite was already everywhere, but it lacked the operational layer that makes a database viable as SaaS infrastructure: networking, replication, managed backups, and a way to run many small databases without drowning in tooling. So centralizing was the path of least resistance, and a `tenant_id`

column in shared Postgres became the reflex.

What changed isn't SQLite. It's that the ecosystem grew the missing parts — and for a growing class of workloads, the thing doing the most frequent writing moved onto my own machine.

SQLite itself is, by design:

`SQLITE_BUSY`

.None of this got fixed by changing SQLite. It got fixed *around* it:

The single-writer model hasn't disappeared, and I still design around it. But "SQLite can't be networked, replicated, or run as shared infrastructure" has stopped being quite as true in practice — so some of the reasons I used to centralize by reflex don't hold for me the way they once did.

A loose model I use to keep the trade-off straight: **state gets pulled toward whatever reads and writes it most.** Put the writer far from the state and you pay the distance on every op — latency, egress, pools, consistency reconciliation. Put them close and most of that disappears.

For two decades the writer was a human clicking a web app: small, occasional, round-trip-tolerant. Weak pull, so central state was fine.

That writer changed. The useful agents run *inside* the work environment — file system, terminal, IDE, browser tab, an already-authenticated session. Codex CLI runs in a local terminal against a directory you choose; Claude Code reads the codebase, edits files, and runs commands on your machine. The strength is **proximity** as much as model quality.

While it works, an agent holds a lot of state: task plan, file index, staged/unstaged diffs, tool-call history, failures and retries, approval state, a local search index, an embeddings cache, sync cursors, idempotency keys, an undo/redo log.

It's high-churn, local, and useless to anyone else. Round-tripping all of it to central Postgres is expensive on three fronts:

Writer moves local → work state follows.

Proximity is one reason. The one I find most underrated is raw hardware — but I want to be careful about *which* case it applies to, because it's easy to overreach here.

It applies to the **resident agent running on the user's own machine** — Claude Code, Codex, and the like, running as desktop/CLI apps, a distinctly desktop-shaped workload. Compare what each side gives that single user. A modern laptop, exclusively: several to a dozen-plus CPU cores, tens of GB of RAM, a fast NVMe SSD, the local file system, sometimes a GPU/NPU, and a session already authenticated as them. A cloud multi-tenant runtime would hand that same user a *slice* — capped CPU, memory, disk I/O, persistent storage — and to run tools safely server-side you'd also need sandboxes, VMs, network controls, permissioning, audit logging, queueing. So even before network latency enters the picture, the local machine often wins on resources per user; the network just widens the gap. Let the model *think* in the cloud — the reading, writing, diffing, indexing, searching, and caching are cheaper where the hardware actually is, and that's the work that generates the local state.

It does **not** automatically carry over to a server-side multi-tenant SaaS agent, where the agent runs in your own infrastructure rather than on the user's laptop — there's no laptop in the loop to be "bigger," so this particular argument simply doesn't apply. The case for SQLite *there* rests on something different: the per-tenant economics, isolation, and blast-radius properties in the next section — not on "the edge has more compute." Two separate arguments for two separate cases, and I don't want to smuggle one in to prop up the other.

The pattern I keep arriving at for SaaS: **one SQLite database per tenant** (or per user, per agent), instead of shared Postgres with `tenant_id`

everywhere and RLS holding isolation together.

Because **a database is a file**, the economics flip:

`WHERE`

clause you hope you never forget.`rm`

, since backups, logs, the warehouse, search indexes, and audit trails still matter, but the operational state isn't scattered across shared tables.The honest costs:

`outbox`

per tenant → event stream → central warehouse. That's infra you now own.The trade: give up effortless cross-tenant analytics and single-migration simplicity; get physical isolation, flatter cost, simple per-tenant lifecycle ops, bounded blast radius. For a lot of the B2B SaaS I work on, that's felt like a good trade lately — though how it nets out depends heavily on the workload, and I wouldn't generalize it past that.

```
  PRIMARY (source of truth)
     │  WAL frames
     ▼
  EDGE REPLICAS  ──── regional, network read
     │
     ▼
  EMBEDDED REPLICA ── in your process, local file read
     │
     └── writes ─────────────▶ forwarded to PRIMARY
```

In both, writes route to a single primary — the single-writer rule reappearing as a **write-latency floor**. US-West primary + Singapore writer = a Pacific round trip, regardless. You design for read-locality and accept write-centralization, which conveniently matches "local work state, central facts."

Consistency isn't free: D1's Sessions API gives sequential consistency within a session and read-your-writes via bookmarks. Adopt replicas, adopt their staleness model *on purpose*.

Scratch state in local SQLite, an embedded replica for fast reads of shared state, vector search in-box for memory. Little of that wants to be a network call to central Postgres.

`tenant_id`

" stopped being the automatic starting point and became one option I weigh among others.`JOIN`

and buy it back with a warehouse. Analytics-first across all tenants? Shared Postgres may still win. Tenant-isolated with roll-ups? Per-tenant tends to win.Three things keep a strict central store:

So the shape is a gradient — fast/disposable at the edge, slow/strict at the center:

```
  SYSTEM OF WORK — the workbench         (local · high churn · disposable)
  ┌──────────────────────────────────────────────┐
  │  Local SQLite          agent / device work     │
  │  Embedded replica      fast local reads         │
  │  Per-tenant SQLite     operational state        │
  └────────────────────────┬───────────────────────┘
                           │
                  ⟨ Event log — sync + audit spine ⟩
                           │
  ┌────────────────────────▼───────────────────────┐
  │  Central ledger (Postgres)  money · billing      │
  │                              inventory · contracts│
  │  Warehouse / search          cross-tenant analytics│
  └──────────────────────────────────────────────┘
  SYSTEM OF RECORD — the vault           (central · slow · strict)
```

Postgres doesn't go away. It stops being where I *start*, and its free cross-tenant analytics moves to the warehouse.

An agent on a laptop edits a customer-facing record. What did it touch? On whose authority? Against what state? Can the team see it without re-deriving it?

The pattern feels right to me, libSQL/Turso seem to show it working in production, Cloudflare shows a zero-ops version — and the major clouds, AWS most of all, haven't shipped the managed tier that would make adopting it boring.

It compounds. As the desktop gets stronger, the browser follows: WASM, OPFS, Web Workers, WebGPU turn the tab from a display surface into a local runtime — which is why a real SQLite file persisting inside a browser tab stopped being exotic. Stronger local execution pulls more state local, and local state pulls SQLite in.

Desktop agents, the browser becoming a runtime, database-per-tenant, the SQLite revival — to me these don't feel like separate trends so much as one shift seen from different angles: the writer moving back to the edge, the tooling finally giving the edge a real database, and state following. It all feels connected — though that's a hunch I hold loosely, not a thesis I'd defend to the death.

Postgres can be the **vault** again. SQLite, per tenant and per agent, becomes the **workbench**. An event log carries the difference.

That's the pull I keep feeling — designing for it a bit more, out of habit a bit less, and still figuring out the edges.
