tracks03 / 04▣ cache — for read scale
A materialized view is a cache the engine keeps exact. Pin your hot queries server-side and every request reads a result that is already correct — the contract is view-after-write == fresh-query, so "stale" stops being a state your system can even be in. Built for public pages where thousands read and few write: a forum's topic list, a storefront, a leaderboard.
01 · pinned queries
A normal live query exists while someone subscribes. A pinned query is materialized with a policy that survives zero subscribers — the daemon keeps it exact on every write so the first request of the day is as warm as the thousandth. Pins are viewer-independent, and one onBootId hook re-asserts them if the daemon restarts.
02 · the one-shot read
Public pages don't want a websocket — they want the current rows, now. handleReadJson resolves a named query once against the warm materialization and returns the rows: the 1-shot endpoint your API server (or edge function) calls to render a page. Same named queries, same authority as the live path — so the cached page and the live app can never disagree.
The same one-shot read is what server rendering uses to preload first paint — one mechanism from "public forum page" all the way up to "hydrated local-first app".
03 · the economics
Re-running a query on every request costs O(table) × readers. Maintaining it costs O(change), once, shared by every viewer. That inversion is what lets one small machine hold a hot public page at load.
cache + invalidate
pin the query
The live wiki board is this track running in public: the real Wikimedia firehose — thousands of edits a minute — held by one pinned query, on one small machine, shared by every viewer.
04 · where it shines
And when one box stops being enough, the pins scale out: a replicated read fleet serves the same named queries through one affinity-aware endpoint — nothing about your queries changes, there are just more cores maintaining them. See scaling reads.
05 · ship it
Pins, the one-shot read, and SSR are all stops on the synced-app path — and you can run just the cache slice of it: the daemon plus a thin API server. No browser engine, no sync protocol, no websockets required.