Self-hostable website analytics on Django: a straightforward collector API, dashboards, a world map, and PDF reports.
analyticsdjangodockerhandcodedpythonself-hostedsqliteviteweb-analytics
1# TODO
2
3## Upgrade SQLite to ≥3.51.3 to close the WAL-reset corruption bug
4
5The `status` repo hit a `database disk image is malformed` corruption on
62026-04-19. Root cause was a two-part interaction:
7
81. **SQLite WAL-reset bug** (introduced 3.7.0, fixed in **3.51.3** released
9 2026-03-13). Triggered when two or more connections on the same file
10 write/checkpoint simultaneously.
112. **`PRAGMA mmap_size=128MB`** amplified a transient WAL inconsistency into
12 structural corruption. SQLite docs explicitly warn against mmap with
13 multi-process writers.
14
15This repo had the same `mmap_size` PRAGMA and the same Alpine 3.21 base, so
16mmap has been removed defensively (commit `9cca9dc`). Risk is lower than
17status because there's no always-on thread-pool scheduler — just gunicorn's
182 workers — but the latent bug still exists because we're stuck on SQLite
193.48.0 (Alpine 3.21).
20
21### Path forward, by preference
22
23- **Wait for Alpine 3.23** to ship SQLite ≥3.51.3 (likely May–June 2026), then
24 bump `FROM alpine:3.21` in the Dockerfile. Zero code change.
25- If it recurs before Alpine 3.23 lands: build SQLite from source in the
26 Dockerfile and `LD_PRELOAD` it, or switch the DB to Postgres.
27
28### Versions checked 2026-04-26
29
30- Alpine 3.21: sqlite-libs 3.48.0 (vulnerable, currently in use)
31- Alpine 3.22: sqlite-libs 3.49.2 (vulnerable)
32- Alpine edge: sqlite-libs 3.53.0 (fixed, but edge isn't appropriate for prod)
33- `pysqlite3-binary` 0.5.4.post2: bundles 3.51.1 (vulnerable; package's last
34 release predates the SQLite fix)