Skip to content

Origin template caching, then transformed-HTML caching #852

Closed

Description

@aram356

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-4962 looks 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 Vary variants bypass it. See docs/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 adapter template_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

  1. 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.
  2. 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.
  3. 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.
  4. Keep response_privacy.rs and 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

Activity

  1. added this to the v1 milestone on Jul 7, 2026
  2. added theissue type on Jul 9, 2026
  3. modified the milestones: v1, 202609 on Sep 1, 2026
  4. assigned and unassigned on Sep 10, 2026
  5. aram356 commented on Sep 14, 2026

    @aram356
    CollaboratorAuthor

    @prk-Jr to check if this still valid issue

  6. prk-Jr commented on Sep 15, 2026

    @prk-Jr
    Collaborator

    Checked against main. Still valid, but most of it landed under #1009 and the remaining
    work is smaller and different from what's written here.

    What's done: item 2 (transformed-HTML caching) is built — core/src/platform/template_cache.rs
    caches 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.rs untouched.

    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 that
    bypass, 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.

  7. changed the issue type fromtoon Oct 1, 2026
  8. changed the issue type fromtoon Oct 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions