Two server-side latency cuts on the Coach drawer open / first turn path.
1. **Per-request memo on `getAssistantFlags()`.** Opening the Coach
drawer fires five gated fetches in parallel — `/api/insights/chat`,
the rail list, `/api/insights/comprehensive`, plus the per-metric
status calls already on the page — and every gated route lands a
`requireAssistantSurface(surface)` call near the top. Today each
call issues its own `AppSettings.singleton` `SELECT`. The new
`src/lib/request-cache.ts` carrier keys a `Map` on the active
`WideEventBuilder` (already in `AsyncLocalStorage` via the
api-handler) so the same request reads the row once. Outside an
event context (unit tests, background jobs) the factory runs
uncached so behaviour is unchanged.
2. **60-second in-memory LRU on `buildCoachSnapshot()`.** A chat
conversation sends 2-4 turns within a minute and the snapshot reads
only persisted data — ~10 measurement reads + GLP-1 + mood + intake
side-fetches per turn. Cache the result keyed on
`(userId, scope.window, sorted scope.sources)` with a 60 s TTL and
a 64-entry LRU cap. Different scopes recompute; the cache evicts
on the next eligible read. Tests exercise both the hit and the
scope-changed miss; legacy tests gain an explicit reset between
describe blocks.
`.planning/round-v1433-audit-perf.md` §3.3 estimates 200-800 ms of
server-side tail saved on the second+ turn and roughly 4×
`AppSettings.singleton` reads avoided on a cold Coach-drawer open.