SQLite Concurrency and Production Deployment

SQLite is the most widely deployed database in the world: it runs inside every phone, browser, and countless desktop applications, and increasingly behind production web applications, edge services, and single-server products. It is a library, not a server — the database is a file, transactions are fully ACID, and there is nothing to operate. For many workloads it is faster and simpler than a client–server database.

Its trade-offs are specific and manageable once understood. SQLite allows many readers but only one writer at a time, so configuration — journal mode, busy timeouts, transaction types — determines whether concurrent access works smoothly or fails with "database is locked". Backups must be taken safely while the database is in use, migrations work within SQLite's ALTER TABLE limits, and the file must live on local storage. This page covers the settings and practices that make SQLite dependable in production.

TL;DR

Quick Example

A connection setup, an explicit write transaction, versioned migrations, and an online backup in Python:

Core Concepts

Locking and Concurrency

SQLite locks the whole database for writes. Any number of connections can read, but only one can write at a time; others wait or receive SQLITE_BUSY ("database is locked"). This is rarely a bottleneck when transactions are short — SQLite can commit thousands of small transactions per second on SSDs — but long write transactions block all other writers.

Journal Modes

In WAL mode, changes accumulate in a -wal file and are copied back to the main database during checkpoints. Long-running read transactions prevent checkpoints from completing, letting the WAL grow; keep reads short and monitor WAL size.

Avoiding "Database Is Locked"

See Database Transactions.

Durability Settings

synchronous=FULL syncs on every commit; in WAL mode, synchronous=NORMAL is commonly used — commits are safe against application crashes, and the most recent transactions could be lost only on power failure or OS crash. Choose based on what the data is worth.

Schema and Integrity

Backups and Replication

Never back up by copying the database file while it is being written — especially in WAL mode, where the -wal file holds recent commits. Test restores regularly. See Database Backups.

Where SQLite Fits

Never place a live SQLite database on a network file system (NFS, SMB): file locking is often unreliable there and corruption can result. See Local-First Software and Mobile App Architecture.

Best Practices

Configure Every Connection

Apply WAL mode, busy timeout, foreign keys, and synchronous settings consistently in one connection factory.

Use BEGIN IMMEDIATE for Writes

Acquire the write lock up front to avoid lock-upgrade failures under concurrency.

Keep Transactions Short

Do slow work outside transactions and batch many small writes into one transaction when possible.

Back Up Online and Test Restores

Use the backup API, VACUUM INTO, or continuous replication, and verify restores.

Common Mistakes

Default Settings Under Concurrency

Copying the Live File

Assuming Foreign Keys Are Enforced

FAQ

Can SQLite handle concurrent users?

Yes for reads, and for writes when transactions are short: SQLite serializes writers, and in WAL mode readers continue during writes. Workloads with heavy, sustained concurrent writes across many processes are a poor fit.

What is WAL mode in SQLite?

Write-ahead logging, a journal mode where changes are appended to a separate log file so readers can continue reading a consistent snapshot while a writer commits.

Why do I get "database is locked" errors?

Another connection holds a lock and your connection did not wait, or a deferred transaction tried to upgrade to a write lock while another writer was active. Use a busy timeout, WAL mode, short transactions, and BEGIN IMMEDIATE.

How do I back up a SQLite database safely?

Use the online backup API, the CLI's .backup command, VACUUM INTO, or a continuous replication tool such as Litestream — not a raw file copy of a database in use.

Is SQLite suitable for production web applications?

For many single-server applications, yes, with proper configuration, backups, and an understanding of its single-writer model. Applications needing many servers writing to one database usually need a client–server database or a replicated SQLite variant.

Related Topics

References