skip to content

A prerendered route gains an interception step stamping a unique per-response token into a security header — what does that cost the shared copy?

level: seniorimportance: should knowfreq 52%

answer

  1. the value must appear twice
  2. prerendered bytes predate the value
  3. header-only varying keeps the body shared
  4. render per request or substitute in flight
  5. constant headers cost prerendering nothing

basics

~20 s

A value unique to each request makes the response no longer identical for every visitor. Headers can still be stamped per response, but markup that must carry the same value can no longer come from a shared prerendered copy.

solid answer

~40 s

Stamping a header is cheap: the step wraps the downstream work, so it can add a field to the outgoing response without touching the body. The problem is the pairing. A per-request token is only useful when the markup carries the same value, and prerendered markup was produced once, at build time, for everybody — it cannot carry a value minted after it was written. So either the route stops being served from the shared copy and renders per request with the token handed in, or the markup is rewritten as it streams out, or the policy for those routes is expressed with constant values so the shared copy survives. Constant headers cost prerendering nothing; only the per-request value does.

go deeper

for a junior

Know that a value minted per request cannot be inside markup that was written once at build time, and that headers and body are two different halves of the same mechanism.

for a middle

Explain which mutations keep a response shareable: a constant header leaves the bytes alone, while a value the markup must contain forces a render per request.

for a senior

Weigh the options out loud — render the route dynamically, substitute during streaming, or split the policy by route — and name what each one gives up in latency, cost or complexity.

for a principal

Decide per route rather than globally, and be explicit that the route now pays both the station's invocation and the render it used to avoid.

## The two halves of a per-request value A per-request token is a **pairing mechanism**: a value minted fresh for one response, sent in a response header, and repeated inside the document so the browser can tell which parts of the markup the policy in the header vouches for. Its value comes entirely from being unguessable and from not being reused, which is precisely what makes it awkward for anything cached. Per-request interception is a natural place to mint it. The step already runs once per matched request, before anything downstream, and it can attach header fields to the outgoing response without inspecting or rewriting the body. Minting here means one place owns the value and every response in the matched set gets one. The catch is the other half. The token must also appear in the markup, and the step does not write markup. ## Why a prerendered copy cannot carry it A prerendered route's HTML is produced **once**, ahead of any request, and stored so that later requests are answered by handing over the same bytes. There is no point during that delivery at which a value invented milliseconds ago can be woven into the stored bytes — unless something rewrites them on the way out, which is a per-request transformation, not a plain cache hit. | What the step adds | Effect on the shared copy | |---|---| | A header with a constant value | None — the bytes are untouched and still shared | | A header derived from the request, with nothing in the body | Body stays shared; only the header field varies per response | | A `Set-Cookie` for the response | Body stays shared, but the response is now client-specific in a way caches must be told about | | A token that must also appear in the markup | The markup must be produced per request; the shared copy can no longer answer alone | The general rule the table encodes: **a value that only lives in headers leaves the body cacheable; a value the body must contain makes the body per-request.** ## The options, and what each gives up 1. **Render those routes per request.** The step mints the token and passes it inward — commonly by adding a request header the render step reads — and the route emits markup containing it. Correct and simple; you have traded the prerendered copy for a render on every request. 2. **Keep the copy and transform on the way out.** Some hosting targets can stream a response through a transformation that substitutes a placeholder for the freshly minted value. The bytes stay cached and the per-request work is a substitution rather than a render, but you now depend on that capability and on the placeholder never escaping unreplaced. 3. **Split the policy by route.** Prerendered routes get a policy expressed without a per-request value, and routes that are already dynamic get the token. This keeps the cheap routes cheap at the cost of two policies to reason about — and the static policy must still be strict enough to be worth having. 4. **Move the constant part down.** Headers with fixed values need not be minted in application code at all; a rule applied by the hosting target attaches them without waking your step, and nothing about the shared copy changes. ## The general lesson This is the clearest instance of a rule that governs the whole station: **anything the step does that makes one response body differ from another pushes that route off the shared answer.** Choosing a variant by a request header or embedding a request-scoped value both have that shape. Deciding *without* varying the body — inspecting and continuing, redirecting some requests entirely, adding a constant header — leaves the cached copy intact. Note also what does **not** change: the step still runs for every matched request either way. Prerendering saves the render, not the invocation. A team that adds a per-request value to a hot prerendered route is therefore paying twice — once for the station it now crosses, once for the render it no longer avoids — and should know that before the change ships, not after the latency graph moves. Meta-frameworks differ in how much of this they will do for you: some route a prerendered page through a per-request pass automatically once anything request-specific is declared, others leave the page cached and require you to opt the route into dynamic rendering explicitly. Either way the trade is the same one, and it is worth making deliberately per route rather than globally.

  • How does the freshly minted value reach the render step if the interception step never sees the markup?
    By passing it inward on the request: the step attaches a request header carrying the value and lets the request continue, and the render step reads that header and emits it in the markup. The step then also sets the matching response header, so both halves agree without the step ever touching the body.
  • Why can the same token not simply be baked into the prerendered markup at build time?
    Because a value stored with the bytes is served identically to everyone for as long as the copy lives, which removes the one property that made it worth having. A fixed value is readable by anyone who views the source once, so it certifies nothing about the current response.
  • Which response mutations at this station leave a shared copy intact?
    Those that do not make the body differ: a constant header field, a decision to redirect some requests away entirely, or an internal rewrite to another route that has its own copy. Varying the body per request, or attaching a per-client cookie the body depends on, is what forces a per-request render.

A stamp on the envelope can differ for every letter, but a serial number printed inside the letter means the letters can no longer be run off in advance from one plate.

saying these in an interview costs you the question

  • Bakes one fixed token into the prerendered markup
  • Thinks a per-response header alone makes the body uncacheable
  • Assumes prerendering also skips the interception step's invocation
  • Expects the step to edit the rendered body it adds headers to
  • Applies a request-varying value to every route and calls it free