perf(viewer): deduce spaces lazily instead of the full database in SSR#251
perf(viewer): deduce spaces lazily instead of the full database in SSR#251jamesdabbs wants to merge 1 commit into
Conversation
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
pi-base-topology | e928786 | Commit Preview URL Branch Preview URL |
Jun 28 2026, 08:29 PM |
a665198 to
6e44d20
Compare
Deploying topology with
|
| Latest commit: |
e928786
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://8c7ced7c.topology.pages.dev |
| Branch Preview URL: | https://perf-viewer-ssr-deduction.topology.pages.dev |
81d7c67 to
cb950ba
Compare
The universal layout load runs during SSR, and refresh() ran the full deduction engine over every space on each request — then the client threw it away and recomputed it after hydration. One logged invocation spent 440ms of CPU rendering a single static reference page; only 3 routes are prerendered, so every detail page (exactly what crawlers and deep links hit) paid this. Gate the eager full-database deduction to the browser, and have checked(spaceId) deduce only the space it needs on demand so SSR of the trait page still renders the data it references. As a side effect this removes the duplicate deduction passes the old test documented as a FIXME. Instrumentation: add a `deduce_space` Workers Logs event (space id + derived count). After this change an SSR page render should emit exactly one `deduce_space` for the requested space, and `deduce_run` (the full-database pass) should disappear from runtime logs entirely — the signal, alongside the platform's per-invocation cpuTimeMs, that the per-request prover work is gone. Stacked on the isolate bundle cache so a warm isolate now reuses both the parse/transform and skips the full prover.
cb950ba to
e928786
Compare
Telemetry validation — deployed to
|
| percentile | baseline (#254) | #251 |
|---|---|---|
| p50 | 889 ms | 265 ms (~3.4× lower) |
| p90 | 2621 ms | 404 ms |
| p99 | 3654 ms | 404 ms (~9× lower) |
The residual ~265 ms is base SSR render + occasional cold-isolate bundle transform; the 0.6–3.6 s of per-request prover work is gone.
Caveats / honesty on the sample
- The post-deploy window is a low-traffic evening lull (~6–22 SSR invocations in 41 min), so the p90/p99 above rest on a small sample (p90≈p99 because there are only a handful of points). The median and the
deduce_run→0 result are robust; the tail magnitude should be re-confirmed over a busier soak. - That cuts in our favor: low traffic means a higher cold-isolate fraction (more cold parses), so a busy-traffic window should land at or below these numbers, not above.
- The baseline row is the perf(viewer): cache the parsed SSR bundle per isolate #254 afternoon busy window (13:00–16:00 UTC, thousands of samples).
Reproduce
- Query Builder: https://dash.cloudflare.com/78c505984bbdc3e69206eecb9471c4de/workers-and-pages/observability/investigate
- Filters:
$metadata.service = pi-base-topology;evt = deduce_run/deduce_space; heavy-route CPU via$workers.event.request.path ~ ^/spaces/[^/]+/properties/[^/]+$over$workers.cpuTimeMs.
Verdict: behaves correctly (deduced traits SSR'd with proofs), eager deduction eliminated, and per-render CPU down ~3.4× median / ~9× p99. Recommend one more soak through a busy-traffic window to firm up the tail percentiles before merge.
What & why
The universal layout load runs during SSR, and
refresh()ran the full deduction engine over every space on each request — then the client discarded it and recomputed the same thing after hydration. One logged invocation spent 440 ms of CPU rendering a single static reference page. Only 3 routes are prerendered, so every detail page (exactly what crawlers and deep links hit) paid this.Gate the eager full-database deduction to the browser, and have
checked(spaceId)deduce only the space it needs, on demand — so SSR of the trait page still renders the data it references. Side effect: removes the duplicate deduction passes the old test documented as a FIXME.Instrumentation
Adds a
deduce_spaceWorkers Logs event (space id + derived count). After this change an SSR page render emits exactly onededuce_space(the requested space), anddeduce_run(the full-database pass) disappears from runtime logs.Tradeoff
SSR'd space pages show only asserted traits in the initial HTML; deduced ones fill in after hydration (unchanged from how the client already worked). If SEO on derived traits matters, prerendering all routes is the follow-up.
Validation
pnpm --filter viewer tscandvalidate(svelte-check) — cleanpnpm --filter viewer test— 70 passed, 5 todo (the FIXME duplicate-pass assertions are gone)VITE_SITE=topology pnpm --filter viewer buildManual deploy + telemetry check (topology worker
pi-base-topology):VITE_SITE=topology pnpm --filter viewer buildpnpm --filter viewer cf:deploy:topology(=wrangler deploy --env topology)/spaces/<id>/properties/<id>page.deduce_spaceper render (the requested space), and nodeduce_runfrom SSR invocations.cpuTimeMson the detail routes (request.routeId) before vs after: should drop from ~440 ms toward low tens of ms.Reviewing
Easiest commit-by-commit; base is #254.