SQLITE_BUSY: database is locked means another connection is writing to the database and SQLite canβt acquire a write lock.
Why this happens
SQLite uses file-level locking β only one process can write at a time, and writers block readers in the default journal mode. This is by design: SQLite targets embedded and single-writer workloads, not high-concurrency servers. The error surfaces when a second connection attempts to write while the first still holds the lock.
What causes this error
- Multiple processes writing simultaneously β SQLite canβt handle concurrent writers
- Long-running transactions β holding a write lock too long blocks others
- NFS or network filesystems β file locking is unreliable on network mounts
Fix 1: Enable WAL mode
PRAGMA journal_mode=WAL;
WAL (Write-Ahead Logging) allows readers and one writer to operate concurrently. This alone fixes most locking issues.
Fix 2: Set a busy timeout
# Python
conn = sqlite3.connect('mydb.db', timeout=10) # Wait up to 10 seconds
# Node.js (better-sqlite3)
const db = new Database('mydb.db', { timeout: 10000 });
Fix 3: Use a single connection for writes
If your app has multiple threads/processes, funnel all writes through a single connection or use a write queue.
Alternative solutions
Use BEGIN IMMEDIATE instead of BEGIN to acquire the write lock upfront, avoiding mid-transaction lock failures:
BEGIN IMMEDIATE;
INSERT INTO posts (title) VALUES ('Hello');
COMMIT;
Prevention
- Keep write transactions as short as possible β do computation outside the transaction, then write.
- Never use SQLite on a network filesystem (NFS, SMB). Use a local disk or switch to PostgreSQL.
When to switch from SQLite
If you consistently hit locking issues with concurrent writes, itβs time to switch to PostgreSQL. SQLite is designed for single-writer workloads. PostgreSQL handles concurrent writes natively.
Related: PostgreSQL Connection Refused fix Β· MongoDB vs PostgreSQL