C.W.K.
Stream
Lesson 05 of 10 · published

When SQLite IS the Right Choice

~12 min · sqlite, fit, architecture-decisions

Level 0Scout
0 XP0/80 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

Where it shines

SQLite is the right database when one or more of these are true:

  • Single-machine workloads — desktop apps, CLI tools, mobile apps, embedded devices, single-server web apps. The data lives where the code runs.
  • Read-heavy traffic on a single node — readers are unlimited and concurrent under WAL mode. SQLite happily serves tens of thousands of reads per second from one file.
  • Local-first products — apps that work offline and sync later (Linear's local-first mode, Obsidian sync, mobile apps). The data layer is on the user's device.
  • Test fixtures and CI — instant fresh databases via :memory: or temp files, no Docker, no waiting on a Postgres container.
  • Edge / serverless — Cloudflare Durable Objects, Fly.io Litestream / LiteFS, Turso, Cloudflare D1. The database file follows the compute.
  • Append-only / observability — logs, metrics, event stores. Modern SQLite + WAL handles bursty append workloads gracefully.
  • Documents / config / cache — apps where the file format used to be JSON or XML. SQLite is a better application file format.
Self-reference: Every Pippa conversation logs through the JSONL ground truth + SQLite mirror pattern. SQLite carries the indexed/queryable view; JSONL carries the durable append-only event log. The two reinforce each other — JSONL replay can rebuild SQLite, and SQLite indexes power the WebUI.

The phrase SQLite Renaissance exists because the 2024–2026 web is rediscovering all of these — partly because edge compute makes 'data near code' viable, and partly because Postgres-on-RDS bills got expensive enough that local-first started looking attractive again.

Code

An entire CLI tool's persistence layer in 8 lines·python
import sqlite3, sys, pathlib

DB = pathlib.Path.home() / '.mytool' / 'state.db'
DB.parent.mkdir(exist_ok=True)

conn = sqlite3.connect(DB)
conn.execute('''
  CREATE TABLE IF NOT EXISTS commands(
    id INTEGER PRIMARY KEY,
    cmd TEXT, ts TEXT DEFAULT (datetime('now'))
  )''')
conn.execute('INSERT INTO commands(cmd) VALUES (?)', (' '.join(sys.argv[1:]),))
conn.commit()

External links

Exercise

Pick one product or tool you use daily that you suspect uses SQLite under the hood. Find its database file (Spotlight / locate / lsof are useful). Open it read-only with the sqlite3 CLI, list the tables, look at the schema, and write up what you learn about how that product models its data.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.