database · tutorial · sqlite

SQLite in Prod Is Fine. You're Just Missing 3 Settings

SQLite survives production with three settings: WAL mode, nightly VACUUM INTO snapshots, and honest limits. The prod config inside.

The paddle tug Seaburn towing the much larger cargo ship Tanea down the River Tyne, black smoke pouring from its funnel
The paddle tug Seaburn towing the much larger cargo ship Tanea down the River Tyne, black smoke pouring from its funnel · Photo: Tyne & Wear Archives & Museums, no known restrictions, via Wikimedia Commons

"SQLite isn't a production database"

Every forum thread says it. SQLite is for tests, demos and mobile apps. Real production needs Postgres.

So founders provision managed Postgres on day one.

Connection strings.

Poolers.

SSL certs. $15 to $50 a month before the first user.

Then the app serves 500 daily users, 99% reads, and the managed database idles at 2% CPU while the founder debugs connection-pool exhaustion they never needed.

The "production database" created production problems the toy would never have.

One file.

Local fast storage.

A backup story simpler than any dump pipeline.

Boring technology, honestly configured.

Default SQLite or production SQLite

Concern Defaults, for dev Production config
Journal mode Delete, one writer blocks everything WAL, readers never block
Durability Relaxed settings Crash-safe settings
Backups Copy the file, corruption risk VACUUM INTO snapshots
Concurrency One writer at a time One writer and unlimited readers
Corruption recovery Hope A daily snapshot

Defaults are dangerous in production. Three reasons.

Copying a live database corrupts backups. The file changes mid-copy. The "backup" restores to garbage exactly when you need it. Snapshots must come from the engine, never from cp.

Delete-mode journals serialize everything. One write blocks all reads. On a busy checkout minute, reads queue behind writes and latency spikes to seconds. WAL mode is the single setting with the biggest production impact.

Checkpoints need scheduling, not hoping. WAL files grow until checkpointed. Neglected, they eat disk and slow recovery. An hourly checkpoint plus size monitoring turns growth from surprise into routine.

What to do

Start every connection with production settings.

Write-ahead logging, so readers never block writers.

Foreign keys on, so the integrity your app assumes is enforced.

A busy timeout, so a locked database waits instead of failing.

A modest memory cache and in-memory temporary tables for speed.

Use the same settings on your laptop and the server. Parity prevents "works locally" mysteries.

Confirm by asking the database for its journal mode and seeing wal. Do not assume.

Snapshot daily. Verify on a schedule.

A consistent snapshot every day, while the app serves. No downtime. No locks held against traffic.

Restore one to staging every month and run your smoke checks against it. A backup never restored is a rumor.

Know the two triggers that end the SQLite era.

Write contention: writers queueing because the database is busy. And geography: users on two continents who need local reads from one place.

Either one firing, with a trend and not a single spike, means graduating to Supabase or MongoDB. The switch is a settings change plus a rehearsed data move. The day is boring on purpose.

The production SQLite scorecard

Check How Healthy looks like
WAL active Ask for the journal mode wal
Log file sane Look at the file next to the database Small, not gigabytes
Snapshot fresh bp status Today's file listed
Restore works A monthly staging restore Smoke checks pass
Contention low Watch for lock-wait errors Rare to none

The honest ceiling

One writer at a time. One file in one place. No multi-region reads.

At indie volumes, writes are cheap and reads scale well. BoringPush publishes no user-count benchmark, so measure your own workload.

Know this first

One writer at a time. One file in one place. BoringPush publishes no user-count benchmark.

Measure your own workload.

Why BoringPush is the way to do this

A production database from the first clone.

BoringPush starts SQLite with safe settings, trims its log hourly and snapshots it daily.

When it outgrows one box, you flip a setting.

FAQ

Is this enough for real customer data?

Yes, with the three disciplines here: write-ahead logging for concurrency, crash-safe settings and verified snapshots for recovery. Durability is proven by restores, not by vendor logos. Rehearse monthly.

How large can the SQLite file grow?

Very large files work fine, and the practical limits are disk size and backup windows, not the engine. Watch how long snapshots take. When they outgrow their window, archive cold rows such as old analytics before blaming the engine.

What about concurrent writes from webhooks plus users?

Keep transactions short and fast. Webhook handlers do small indexed writes in milliseconds. Contention appears only when a transaction holds a lock across a network call, so read and compute outside the transaction and write quickly.

Should the log files live on a different disk?

On one VPS, no. The same disk keeps crash behavior simple. Keep verified snapshots elsewhere, and send off-box copies weekly.

How do I monitor SQLite health without a managed dashboard?

Watch five things: log file size, snapshot freshness, file growth, lock-wait errors and your server's memory. Critical failures reach you by alert, and bp status shows the rest. The alerting matters more than the charts.

When exactly do I switch to Postgres or MongoDB?

When a trigger fires with a trend: contention climbing for weeks, or latency that demands geography. Rehearse the migration on staging, change the database setting, and keep your SQLite snapshots for a month. It is a graduation, not an escape.

Keep reading

+ 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