Skip to main content

Posts

Showing posts with the label SQLite

Fixing SQLite 'SQLITE_BUSY: database is locked' in Concurrent Edge Environments

  If you are deploying SQLite in a Node.js environment—whether on a distinct VPS, inside a Docker container, or via a stateful edge provider like Fly.io—you have likely encountered this stack trace during load testing or production spikes: SqliteError: SQLITE_BUSY: database is locked at Statement.run (node_modules/better-sqlite3/lib/methods/wrappers.js:5:11) ... This error usually creates a false dichotomy for developers: "SQLite isn't production-ready" or "I need to migrate to Postgres immediately." Neither is necessarily true. The issue is rarely SQLite itself, but rather the default configuration regarding concurrency and file locking. Here is the root cause analysis and the definitive implementation to handle high-concurrency writes in Node.js. The Root Cause: Rollback Journals and Exclusive Locks By default, SQLite uses a  Rollback Journal . To write to the database in this mode, SQLite must acquire an  EXCLUSIVE  lock on the database file. The Lock...

Solving 'SQLITE_BUSY: database is locked' with WAL Mode and Busy Timeouts

  You have likely encountered   SQLITE_BUSY   (or   OperationalError: database is locked ) just as your application scales beyond a single user. It is the most common reason developers abandon SQLite for Postgres or MySQL prematurely. The error occurs not because SQLite is incapable of concurrency, but because its default configuration prioritizes safety and backward compatibility over concurrent performance. By understanding SQLite's locking mechanism and adjusting two specific settings—Journal Mode and Busy Timeout—you can handle high-throughput concurrent workloads in Node.js and Python without migration. The Root Cause: Rollback Journals and Exclusive Locking To understand the fix, you must understand the locking model. By default, SQLite uses a  Rollback Journal  (specifically  DELETE  mode). When a connection needs to write to the database: It acquires a  SHARED  lock to read data. It acquires a  RESERVED  lock to signal ...