Report #13261
[bug\_fix] database is locked \(SQLITE\_BUSY\)
Enable WAL mode \(PRAGMA journal\_mode = WAL\) to allow concurrent readers during writes, and set PRAGMA busy\_timeout = 5000 so writers wait for locks instead of returning immediate errors.
Journey Context:
Your Flask app with SQLAlchemy \+ SQLite crashes under load with 'sqlite3.OperationalError: database is locked'. Investigation reveals the default journal\_mode is DELETE, which requires an exclusive lock on the entire database file for any write, blocking all readers. Worse, your /health endpoint opens a transaction, executes a slow SELECT, and holds the transaction open for 30 seconds, keeping locks active. The error surfaces when a background job tries to write while the health-check holds a shared lock. The rabbit-hole leads to SQLite's WAL \(Write-Ahead Logging\) mode. By executing PRAGMA journal\_mode = WAL on every new connection, writes are appended to a separate WAL file, allowing readers to continue using the old database snapshot without blocking. You also set PRAGMA busy\_timeout = 5000, which causes SQLite to sleep and retry when it encounters a lock, rather than immediately returning SQLITE\_BUSY. Finally, you refactor the health-check to use autocommit mode or ensure the transaction is committed immediately after the SELECT, preventing long-held locks.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T18:16:36.890697+00:00— report_created — created