Repository navigation
Origin template caching, then transformed-HTML caching #852
Description
Description
The 2026-07-05 performance and architecture review proposed two layers: cache a safe origin HTML template, then cache the transformed, auction-independent HTML and splice per-request bids. The second layer now exists as an experimental, opt-in Fastly Core Cache path with [creative_opportunities] assembly_mode = "esi". On an eligible warm hit it serves a reader-neutral transformed template before the origin fetch and HTML rewrite; the final assembled response stays private. Other adapters fall back to inline transformation.
The older claim that the repository has no cache API or that every pageview must fetch and rewrite is now stale. The remaining decision is whether a separate origin-template cache yields useful coverage where transformed-template sharing cannot, and how it composes safely with the existing cache.
Current behavior and gaps
crates/trusted-server-core/src/publisher.rs:4873-4962looks up a transformed template before origin fetch. The Fastly backend uses Core Cache (crates/trusted-server-adapter-fastly/src/template_cache.rs).- Sharing is limited to eligible GET HTML with explicit positive origin shared freshness and request/response privacy checks. Cookie-dependent, private, uncacheable, or uncovered
Varyvariants bypass it. Seedocs/guide/configuration.md, “Shared template assembly.” - The template backend already sets a global and per-URL surrogate key and exposes purge operations (
platform/template_cache.rs:158-169; Fastly adaptertemplate_cache.rs:255-286). A CMS-to-template purge contract still needs to be specified and verified. - The origin fetch on a cold or bypassed request still pays origin latency and the rewrite cost. A separate origin-template cache has not been demonstrated to improve those paths; its value needs measurement.
Proposed work
- Measure origin fetch, rewrite, cache hit, and bypass rates on representative page types. Identify which safe, frequently requested URL variants miss the transformed-template cache and why.
- If the measurements justify another layer, design an origin-template key using URL, host, and every origin-controlled variant. Define cookie handling explicitly; do not strip cookies from a request unless the origin is proven cookie-independent for that route. Respect private/no-store,
Vary, authorization,Set-Cookie, TTL, and stale-while-revalidate policy. - Connect CMS invalidations to the existing per-URL/global surrogate-key mechanism, or document the exact operator purge path and its limits. Avoid emitting shared-cache headers on the personalized final response.
- Keep
response_privacy.rsand its browser/privacy downgrade behavior intact.
Done when
- Measurements show the remaining origin/rewrite cost and identify the traffic an origin-template layer would cover.
- A documented go/no-go decision states whether to build that layer; if yes, its key, privacy rules, freshness, stale behavior, and invalidation contract are specified and tested.
- CMS/operator purge behavior for transformed templates is documented and validated.
- Final per-reader HTML remains private across both cache-hit and fallback paths.
Related
- Original review: 2026-07-05 performance and architecture review, sequencing item 6 of 10.
- Validate ESI approach to cache fragments on pages to separate cachable content for per-user events #1009 — experimental transformed-template cache work.
Activity
aram356 commentedon Sep 14, 2026
@prk-Jr to check if this still valid issue
prk-Jr commentedon Sep 15, 2026
Checked against
main. Still valid, but most of it landed under #1009 and the remainingwork is smaller and different from what's written here.
What's done: item 2 (transformed-HTML caching) is built —
core/src/platform/template_cache.rscaches the pre-assembly template and late-binds the bid splice at a seam. Item 3's surrogate
keys are emitted. Item 4 held,
response_privacy.rsuntouched.What's not: item 1 was mis-stated. We don't lack origin caching — we opt out of it, with
set_pass(true)on every ad-stack fetch (publisher.rs:4415). The fix is narrowing thatbypass, not building a cache. And item 3's purge hooks don't exist; nothing operator- or
CMS-facing calls the purge that's already wired up.
The real blocker isn't in this issue at all: the template cache excludes any request with a
cookie, and we set our own EC cookie, so hit rate is ~0 in production. There's an opt-out
flag but no way to verify it's safe to set.
Suggest keeping this open, rescoped to: narrow the bypass, add a CLI probe for the cookie
flag, add purge CLI + admin endpoint, promote the cache out of spike status, and log
hit/miss so we can actually measure it. Effort drops to Small/Medium. Writing up a spec now.
Make the planning documents describe what was actually built
Split origin shareability from template eligibility, and add the read…