database · tutorial · comparison

SQLite vs Mongo vs Supabase: 2 Triggers End the Debate

Latency, cost, limits, and the two triggers that say switch. Plus the one-var escape hatch that makes it free.

Diagram: app.db with its -wal and -shm sidekicks, plus the DB_PROVIDER exit switch
Diagram: app.db with its -wal and -shm sidekicks, plus the DB_PROVIDER exit switch · Photo: Boring

The most rewritten decision in SaaS

"Which database?" generates more rewrites than any other early choice. Start Postgres, pay rent through zero revenue, fight connection pools at the first spike.

Start Mongo, hand-roll relations you actually needed. Start SQLite, get told it "doesn't scale" by people running 200 users.

The threads agree on the pain and disagree on everything else — because the right answer is temporal: different databases at different revenues, and the switching cost is the whole game.

The table: all three, no romance

Axis SQLite (WAL, NVMe) MongoDB (Atlas) Supabase (Postgres)
Read latency 0.1ms local 5–35ms network 5–35ms network
Cost at start $0 (rides the VPS) Free tier → $9+/mo Free tier → $25+/mo
Cost at scale $0 until one box ends Grows with ops + storage Grows with compute + bandwidth
Relations JOINs, FKs (real SQL) Embedded docs (denormalize!) JOINs, FKs, RLS policies
Connection limits None (file descriptor) Pooled (watch serverless) Pooled (Supavisor helps)
Killer feature Zero ops, instant Flexible schema evolution Auth + realtime + RLS built in
Killer risk One-box ceiling Relation modeling debt Bill + lock-in creep
Switch trigger — (start here) Document-shaped data + Atlas elsewhere RLS/realtime needed, or write contention
SQLite one file, WAL, and the exit
Start on the file, leave by variable: the two triggers are the only exit signs.

Two triggers say switch, and only these two: sustained write contention (busy_timeout errors — readers never trigger it), or a Postgres-only feature you actually use (RLS policies, realtime channels). Everything else — "we might need scale," "investors expect Postgres," "the tutorial used Prisma" — is vibes with a price tag.

Most SaaS never hits trigger one; trigger two is a product decision, not an infrastructure emergency. Try it yourself:

Loading interactive…

The BoringPush escape hatch makes both triggers cheap: identical behavior and field shapes across all three engines, so switching is one database setting plus keys — zero query rewrites, same routes, same paywall guards. Start SQLite, earn the switch, change a setting on a calm Tuesday.

Ship from anywhere on a Next.js stack where the database is a deployment detail instead of a migration project.

FAQ

Is MongoDB "webscale" and SQLite "toy"? (No.)

Both myths. Mongo scales via sharding you'd rarely need; SQLite serves 100k+ ops/sec locally.

Scale is about access patterns and indexes, not logos.

What about Prisma/Drizzle instead of raw parity?

ORMs add a migration-framework dependency and a query-builder dialect to every switch. Raw + identical function names keeps the escape hatch one variable wide.

Fewer layers, fewer 2am surprises.

Do I need connection pooling on SQLite?

No pool exists — that's the feature. One writer serialized via BEGIN IMMEDIATE, readers in parallel.

Pool exhaustion, the classic serverless outage, is structurally impossible.

Supabase vs raw Postgres?

Supabase buys auth/realtime/storage/dashboard in one bill; raw Postgres (RDS/self-hosted) buys control. If you want the ecosystem, Supabase; if you want the minimum, a bigger VPS with Postgres.

BoringPush speaks both.

Can I run two at once (SQLite prod + Supabase analytics)?

Yes — and it's recommended: product reads stay 0.1ms local while heavy aggregations run against the warehouse. Separate files, separate fates.

+ all the boring stuff (analytics, auth, SQLite ↔ Supabase, full marketplace, webhooks)

The Agent-First Shipping Kit

Command from your phone.

Built so autonomous AI agents build what you want without breaking what's already paying you.

$199

Get BoringPush

One-time payment · Lifetime updates · Unlimited projects.

Keep reading