Self-hostable uptime monitor and status page on Django: HTTP checks, Lighthouse audits, SEO crawls, and email and Discord alerts.
djangodockerhandcodedpythonself-hostedsqlitestatus-pageuptime-monitoringvite
1# TODO
2
3## Upgrade SQLite to ≥3.51.3 to close the WAL-reset corruption bug
4
5On 2026-04-19 the production database corrupted with `database disk image is
6malformed` (recovered via `sqlite3 .recover` on 2026-04-26). Root cause was a
7two-part interaction:
8
91. **SQLite WAL-reset bug** (introduced 3.7.0, fixed in **3.51.3** released
10 2026-03-13). Triggered when two or more connections on the same file
11 write/checkpoint simultaneously. The scheduler runs 4 worker threads with
12 their own Django connections, plus gunicorn — exactly the trigger pattern.
132. **`PRAGMA mmap_size=128MB`** amplified a transient WAL inconsistency into
14 structural corruption (`Child page depth differs`, `2nd reference to page X`
15 — classic mmap-spread signatures). SQLite docs explicitly warn against mmap
16 with multi-process writers.
17
18Mitigations already applied (commit `dca4328`): dropped `mmap_size`, reduced
19gunicorn to 1 worker. mmap removal is the meaningful fix — it eliminates the
20amplifier so a transient WAL race is self-correcting. **The bug itself is
21still latent** because we're stuck on SQLite 3.48.0 (Alpine 3.21).
22
23### Path forward, by preference
24
25- **Wait for Alpine 3.23** to ship SQLite ≥3.51.3 (likely May–June 2026), then
26 bump `FROM alpine:3.21` in the Dockerfile. Zero code change.
27- If it recurs before Alpine 3.23 lands: build SQLite from source in the
28 Dockerfile and `LD_PRELOAD` it, or switch the DB to Postgres (analytics
29 already runs on it).
30
31### Versions checked 2026-04-26
32
33- Alpine 3.21: sqlite-libs 3.48.0 (vulnerable, currently in use)
34- Alpine 3.22: sqlite-libs 3.49.2 (vulnerable)
35- Alpine edge: sqlite-libs 3.53.0 (fixed, but edge isn't appropriate for prod)
36- `pysqlite3-binary` 0.5.4.post2: bundles 3.51.1 (vulnerable; package's last
37 release predates the SQLite fix)