# Does one sqlite connection make reads queue? No (V-642) Measured 07-08-2026 at `7b507de`, on homesrv. The harness is `internal/store/conncap_test.go`. It stays in the repo, because this claim gets re-argued and the numbers should be re-runnable rather than quoted. `internal/store/store.go` opens the database with `SetMaxOpenConns(1)`, while `schema.sql` sets `journal_mode=WAL`. WAL exists to let readers run beside one writer, so the cap gives up the thing the journal mode was chosen for. The question was whether that costs anything. ## What was measured A fixed two-second window. One writer calling `SetValue` paced at 2ms, and a reader loop calling `RecentFacts(50)` over 500 seeded rows as fast as it can. Same schema, same modernc driver, same machine, three runs per cap. The window is wall-clock rather than a read count on purpose. A first version ran a fixed 300 reads. That finished sooner at the higher cap, so it received fewer writes, and two runs that did different work cannot be compared. | cap | reads | writes | p50 | p95 | max | |---|---|---|---|---|---| | 1 | ~3050 | ~760 | 594µs | 900µs | 16-19ms | | 4 | ~3600 | ~340 | 525µs | 710µs | 1-2ms | ## What it says **Reads do not queue behind writes.** Four connections buy about 70µs at p50. A turn spends 1.19s in the resident model. The tail does improve, from 19ms to 2ms, and 19ms is still not a figure anyone notices in a spoken reply. **Write throughput more than halves at the higher cap**, 760 writes against 340. inference, not measured directly: at one connection the reader and the writer take turns with no lock contention. At four the writer contends for the WAL write lock with a live reader. Whatever the mechanism, the trade runs the opposite way from the one the task expected. **The cap was not the source of the 2.7s router figure.** CLAUDE.md records that figure as contention rather than the model. This task was a candidate for where that contention came from. A 19ms worst case cannot produce it. That line of enquiry is closed. **One transaction is what the cap cannot survive.** With a read-only transaction open, a second read at cap 1 never completes. The harness gave it two seconds and got `context deadline exceeded`. The same read at cap 4 took 1ms. The transaction holds the only connection, so this is not a slow read, it is a stalled database. ## What was done The cap stays at 1. The reason is now written where the cap is set, rather than inferred from a four-word comment. `Store.DB` was deleted. It handed out exactly the read-only transaction measured above. It had been there since the initial commit with no production caller, and its doc comment described a loop that never materialised. Its one user was a test helper reading `delivery_attempts` by raw SQL. `ListDeliveryAttempts` has covered that since V-390, and the helper now goes through the reader. So the hazard is gone by construction, not by documentation. `TestConnCap_ReadBlocksBehindOpenSnapshot` is the standing measurement of what re-adding the seam would cost. ## Not answered Whether reads queue on the deployed box under real load, as opposed to a synthetic loop. The harness writes and reads one table. Digestion reads four and embeds while it does. The finding that closes this task is the transaction stall, which is structural and does not depend on load.