On SQLite every statement waits for the disk: a scan takes over a second a feed #135

Closed
opened 2026-10-05 10:02:18 -07:00 by rays · 1 comment
Owner

Found by the load tests (#133) on 2026-10-05. A daemon on SQLite under /tmp on Tower (a loop device, 52ms for one synchronous 4 KB write) scanned 1.3s a feed of 20 items served from the same machine, so 1,500 feeds would take about 50 minutes; subscribing the first admin to an imported catalogue of 1,500 feeds took 39s, before the web server listened.

The database is in WAL mode with SQLite's default synchronous=FULL, so every commit waits for an fsync, and nearly every statement is a commit of its own: a feed's entries and enclosures are written row by row. SQLite's own advice for WAL is synchronous=NORMAL, which syncs at checkpoints instead; a crash of ipx loses nothing, and only a power cut can lose the last transactions, never corrupt the file. Production is on Postgres and unaffected; anyone on the SQLite default is.

Found by the load tests (#133) on 2026-10-05. A daemon on SQLite under /tmp on Tower (a loop device, 52ms for one synchronous 4 KB write) scanned 1.3s a feed of 20 items served from the same machine, so 1,500 feeds would take about 50 minutes; subscribing the first admin to an imported catalogue of 1,500 feeds took 39s, before the web server listened. The database is in WAL mode with SQLite's default synchronous=FULL, so every commit waits for an fsync, and nearly every statement is a commit of its own: a feed's entries and enclosures are written row by row. SQLite's own advice for WAL is synchronous=NORMAL, which syncs at checkpoints instead; a crash of ipx loses nothing, and only a power cut can lose the last transactions, never corrupt the file. Production is on Postgres and unaffected; anyone on the SQLite default is.
rays added the bug label 2026-10-05 10:02:18 -07:00
Author
Owner

Fixed in 367f431: every SQLite connection sets synchronous=NORMAL. In the load harness the first scan of 1,500 feeds went from about 1.3s a feed (est. 50 minutes) to 27s, and subscribing the first admin to them from 39s to 0.75s. Released in 0.10.0, deployed 2026-10-05; production is on Postgres and unaffected.

Fixed in 367f431: every SQLite connection sets synchronous=NORMAL. In the load harness the first scan of 1,500 feeds went from about 1.3s a feed (est. 50 minutes) to 27s, and subscribing the first admin to them from 39s to 0.75s. Released in 0.10.0, deployed 2026-10-05; production is on Postgres and unaffected.
rays closed this issue 2026-10-05 10:12:56 -07:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: rays/ipx#135