The SQLite Bug That Silently Corrupts Data
Tailscale just found a 16-year-old race condition in SQLite's WAL reset. Here is how it destroys databases and how to verify yours.
We treat SQLite like an indestructible foundation. It runs on everything from your iPhone to critical backend infrastructure. Tailscale recently proved that foundation has cracks.
They traced catastrophic database corruption to a 16-year-old bug in SQLite's Write-Ahead Log (WAL) reset logic. This wasn't a bad query or a full disk. It was a silent race condition.
Why this matters
If you use SQLite for local caching, application state, or edge compute, you are likely using WAL mode. It allows concurrent reads while writing.
This bug doesn't throw errors. It doesn't crash your app immediately. It silently writes garbage to your database file during a specific checkpoint and reset sequence, leaving you with corrupted data you won't discover until it's too late.
How it works
When SQLite uses WAL, changes are appended to a separate database-wal file. Readers check this file first to get the latest data.
Eventually, SQLite runs a "checkpoint" to merge the WAL data back into the main database file. After a successful checkpoint, if the WAL file reaches zero bytes, it triggers a reset.
The bug lies in that reset handshake. If a power loss, kernel panic, or filesystem error occurs in the exact microsecond between clearing the WAL header and committing the checkpoint—specifically when the fsync operation fails silently—SQLite gets confused. On the next boot, it assumes the main database is authoritative, even though the writes never finished.
Where this helps
Understanding this edge case is critical if you manage:
- IoT Devices: Power loss is common, making silent corruption during WAL resets a high probability.
- Edge Functions: Serverless environments that freeze or kill containers rapidly can interrupt the checkpoint process.
- Desktop Apps: Users force-quitting applications during heavy write operations.
Watch out
This bug is heavily dependent on your filesystem's behavior regarding fsync. Some operating systems and disk drives lie about flushing data to disk to improve performance benchmarks. If your OS or SSD doesn't guarantee write durability, no database can protect you.
Try it yourself
You cannot trigger the race condition manually, but you can check if your current databases are healthy. Run the integrity_check pragma. If you've been running an older version of SQLite on edge devices, now is the time to audit.
-- Check your SQLite version
SELECT sqlite_version();
-- Verify database integrity
PRAGMA integrity_check;
TL;DR
- What changed: A 16-year-old bug in SQLite's WAL reset logic can cause silent database corruption during power loss.
- Why it matters: SQLite is ubiquitous, and this bug leaves no trace until the data is already gone.
- What to try today: Run
PRAGMA integrity_check;on your critical SQLite databases and update your library.