4. The measurement discipline (how all of this was found)
Server telemetry alone is structurally blind: the request log said 59ms while the user felt 5 seconds. When something "feels slow":
- State a hypothesis, then instrument — never patch on theory. Two confident theories (compression, row keys) were implemented before the real cause was measured; both were fine work aimed at the wrong organ.
- Build the waterfall in the browser:
performancenav/resource timing (TTFB / download / apply), aPerformanceObserveronlongtask, a MutationObserver for apply bursts. The client beacon (static/telemetry.js→sys_metric→ Admin Usage "How it feels") keeps this running permanently. - Distrust an unreproducible number — it usually means a race; find the two racers before measuring anything else.
- SQLite is never guilty until the raw query is timed alone (5ms for 3.5k rows with five joins; the 77ms "slow query" was one missing index probed per-row). Go render cost that smells wrong is usually allocation churn (per-row string concatenation), not templ.
- Measure on the deployed hardware path — localhost hides the wire, the
proxy, and the Pi's CPU. And verify which build is actually running
before trusting any prod measurement (
tr[id]presence, a marker).