Report #61003
[bug\_fix] SQLite WAL file grows unbounded due to checkpoint starvation
In WAL \(Write-Ahead Logging\) mode, committed transactions append to the -wal file. A checkpoint \(automatic or manual\) transfers these pages to the main database and truncates the -wal. However, if any read transaction holds a snapshot of a commit older than the last checkpoint, the checkpoint cannot proceed past that point \(checkpoint starvation\), causing the -wal file to grow indefinitely. The fix is to ensure no long-running read transactions. Specifically, set 'PRAGMA wal\_autocheckpoint = 1000;' \(default is usually fine\), but more importantly, ensure your application does not hold prepared statements or transactions open indefinitely. For immediate relief, run 'PRAGMA wal\_checkpoint\(TRUNCATE\);' when the system is quiescent \(no readers\), which forces a checkpoint and truncates the WAL even if it means waiting for readers to finish.
Journey Context:
You operate a Node.js analytics service using better-sqlite3 with WAL mode for high write throughput. After a week of uptime, monitoring alerts that the disk is 90% full. You investigate and find that database.sqlite-wal is 60GB while database.sqlite is only 5GB. You check PRAGMA wal\_checkpoint; it returns busy=1, meaning a checkpoint is blocked. You examine your code and realize you have a startup routine that runs 'const stmt = db.prepare\('SELECT \* FROM config'\); const config = stmt.get\(\);' but you never call stmt.free\(\) or finalize the statement, and you keep the database connection open forever for reads. This long-lived prepared statement holds back the checkpoint from truncating the WAL past the point when that statement was created. You refactor the code to use db.transaction\(\) for batch reads and ensure all prepared statements are finalized immediately after use. You then run 'PRAGMA wal\_checkpoint\(TRUNCATE\);' to reclaim the 60GB. You add monitoring for the -wal file size. The issue is resolved because checkpoints can now proceed as readers are short-lived, allowing the automatic truncation of the WAL file.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T08:52:52.400749+00:00— report_created — created