{"slug": "why-ai-agents-make-me-reach-for-sqlite", "title": "Why AI Agents Make Me Reach for SQLite", "summary": "A developer argues that AI agents' high-churn, local, and private state makes SQLite a more natural fit than Postgres for agent workloads. The developer notes that the ecosystem around SQLite has matured with networking, replication, and managed backups, reducing the need to centralize data by default. The developer uses Turso with Cloudflare as an example of this stack but wishes for more managed SQLite services from AWS and D1.", "body_md": "Lately I keep reaching for SQLite where, before, I'd have reached for Postgres without thinking.\n\nIt 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?\n\nTurso 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.\n\nThis 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.\n\nWhere I've landed for now (and expect to keep revising):\n\n- SQLite isn't replacing Postgres.\n- For\nwork state, it's increasingly my first reach, not my last.- AI agents push this harder: their state is high-churn, local, and mostly private.\n- The answer isn't all-local. It's a local\nworkbenchplus a centralledger.\n\nFor 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.\n\nSQLite 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`\n\ncolumn in shared Postgres became the reflex.\n\nWhat 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.\n\nSQLite itself is, by design:\n\n`SQLITE_BUSY`\n\n.None of this got fixed by changing SQLite. It got fixed *around* it:\n\nThe 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.\n\nA 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.\n\nFor two decades the writer was a human clicking a web app: small, occasional, round-trip-tolerant. Weak pull, so central state was fine.\n\nThat 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.\n\nWhile 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.\n\nIt's high-churn, local, and useless to anyone else. Round-tripping all of it to central Postgres is expensive on three fronts:\n\nWriter moves local → work state follows.\n\nProximity 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.\n\nIt 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.\n\nIt 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.\n\nThe pattern I keep arriving at for SaaS: **one SQLite database per tenant** (or per user, per agent), instead of shared Postgres with `tenant_id`\n\neverywhere and RLS holding isolation together.\n\nBecause **a database is a file**, the economics flip:\n\n`WHERE`\n\nclause you hope you never forget.`rm`\n\n, 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:\n\n`outbox`\n\nper 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.\n\n```\n  PRIMARY (source of truth)\n     │  WAL frames\n     ▼\n  EDGE REPLICAS  ──── regional, network read\n     │\n     ▼\n  EMBEDDED REPLICA ── in your process, local file read\n     │\n     └── writes ─────────────▶ forwarded to PRIMARY\n```\n\nIn 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.\"\n\nConsistency 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*.\n\nScratch 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.\n\n`tenant_id`\n\n\" stopped being the automatic starting point and became one option I weigh among others.`JOIN`\n\nand 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:\n\nSo the shape is a gradient — fast/disposable at the edge, slow/strict at the center:\n\n```\n  SYSTEM OF WORK — the workbench         (local · high churn · disposable)\n  ┌──────────────────────────────────────────────┐\n  │  Local SQLite          agent / device work     │\n  │  Embedded replica      fast local reads         │\n  │  Per-tenant SQLite     operational state        │\n  └────────────────────────┬───────────────────────┘\n                           │\n                  ⟨ Event log — sync + audit spine ⟩\n                           │\n  ┌────────────────────────▼───────────────────────┐\n  │  Central ledger (Postgres)  money · billing      │\n  │                              inventory · contracts│\n  │  Warehouse / search          cross-tenant analytics│\n  └──────────────────────────────────────────────┘\n  SYSTEM OF RECORD — the vault           (central · slow · strict)\n```\n\nPostgres doesn't go away. It stops being where I *start*, and its free cross-tenant analytics moves to the warehouse.\n\nAn 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?\n\nThe 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.\n\nIt 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.\n\nDesktop 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.\n\nPostgres can be the **vault** again. SQLite, per tenant and per agent, becomes the **workbench**. An event log carries the difference.\n\nThat's the pull I keep feeling — designing for it a bit more, out of habit a bit less, and still figuring out the edges.", "url": "https://wpnews.pro/news/why-ai-agents-make-me-reach-for-sqlite", "canonical_source": "https://dev.to/gyu07/why-ai-agents-make-me-reach-for-sqlite-4dh0", "published_at": "2026-06-17 03:34:20+00:00", "updated_at": "2026-06-17 03:51:27.851382+00:00", "lang": "en", "topics": ["artificial-intelligence", "ai-agents", "developer-tools", "ai-infrastructure"], "entities": ["SQLite", "Postgres", "Turso", "Cloudflare", "D1", "AWS", "Claude Code", "Codex CLI"], "alternates": {"html": "https://wpnews.pro/news/why-ai-agents-make-me-reach-for-sqlite", "markdown": "https://wpnews.pro/news/why-ai-agents-make-me-reach-for-sqlite.md", "text": "https://wpnews.pro/news/why-ai-agents-make-me-reach-for-sqlite.txt", "jsonld": "https://wpnews.pro/news/why-ai-agents-make-me-reach-for-sqlite.jsonld"}}