skip to content

A prerendered route still serves last week's title and preview text after the data changed, though its body updates on load. Why?

level: seniorimportance: should knowfreq 55%

answer

  1. the head is part of the artifact
  2. built once, then only read
  3. the client repair never rewrites the file
  4. regenerate, or render per request

basics

~20 s

The head was rendered into the stored HTML when the page was built and stays frozen there until that page is produced again; only the body is being refreshed by a client fetch after load. Consumers that never execute scripts read the frozen values.

solid answer

~50 s

Prerendering produces an HTML artifact per route ahead of time, and the head is part of that artifact exactly as the body is. Serving it later is a file read, so a title or preview entry computed from data at build time keeps its build-time value however often the underlying record changes. The body looks current because the client refetches after hydration and re-renders it — a repair that never rewrites the stored file, and never reaches a consumer that reads the HTML without executing scripts. The fixes, in rising cost: produce that page again (a full rebuild, a regeneration window after which a request triggers a rebuild, or an on-demand invalidation fired by the change); render the route per request if its head is genuinely volatile; or keep the head on stable facts and let the volatile ones live in the body. Caches in front hold their own copy, so invalidate those too.

go deeper

for a junior

Remember that a prerendered page's head is stored in the same file as its body, so changing the source data does not change what has already been stored.

for a middle

Explain why the body can look fresh while the head does not: the client refetch repairs the rendered document, never the stored artifact.

for a senior

Diagnose from the served bytes, then choose between producing the page again, rendering per request and narrowing the head's dependencies — and invalidate the caches in front.

for a principal

Decide which routes may put volatile data in the head at all, and what triggers regeneration, before a freshness expectation is written into a product requirement.

## What prerendering actually stores Producing a route ahead of time means running the route once during a build — data step, head computation, body render — and storing the resulting HTML. At serve time there is no rendering left: the request is answered from that stored artifact, possibly by a cache that never even asks the origin. The point people miss is that **the head is inside the artifact**. It is not assembled per request and pasted onto a stored body; the whole document, head included, was serialised at build time. So every computed head entry holds the value its inputs had at build time, and keeps it until the artifact is produced again. ## Why the body looks fresh and the head does not The body appears current because the page repairs itself in the browser: after hydration a client fetch pulls the present state and re-renders. That repair happens in **one browser's live document**. It does not rewrite the stored file, and it does not run at all for a consumer that never executes scripts. | consumer | executes the page's scripts | what it sees | |---|---|---| | a person in a browser | yes | stored head, then a repaired body | | a link-preview fetcher | usually no | the stored head, unchanged | | a crawler or archiver that does not run scripts | no | the stored head, unchanged | | a plain HTTP client | no | exactly the stored bytes | That table is also the diagnosis procedure. Fetch the URL as a plain request and read the head in the returned bytes; comparing against the browser's rendered document proves nothing, because the client has already repaired it there. ## The repair options 1. **Rebuild the page.** The direct fix: run the route again so a new artifact replaces the old one. A full build is the blunt version and can be slow on a large site — and do not assume a redeploy alone rebuilds everything, since build caching may reuse artifacts whose inputs it believes unchanged. 2. **A regeneration window.** The stored page is marked stale after some interval; the next request makes it eligible to be produced again, typically serving the existing copy while the new one is made. Freshness is bounded by the window, and the first request after expiry may still receive the old head. 3. **On-demand invalidation.** The system that changed the record tells the framework to drop the affected page. The fix is prompt, but every mutation path has to fire the trigger, and a path that forgets leaves a page stale indefinitely. 4. **Render per request.** If the head is genuinely volatile, stop storing the page. You pay render time on every request and gain a head that is always current. 5. **Narrow the head's dependencies.** Often the strongest option: keep in the head only facts that change on the same cadence as the page is produced, and let the volatile numbers live in the body where the client repair is legitimate. | option | freshness | cost | |---|---|---| | rebuild | as often as you build | build time, all pages | | regeneration window | bounded by the window | one stale response per expiry, per page | | on-demand invalidation | near-immediate | wiring every mutation path | | per-request rendering | always current | render on every request | | narrower head | not needed | a product conversation about what belongs in the head | ## Everything in front holds a copy Regenerating the artifact is not the end of it. A cache in front of the origin keeps its own copy of the document and will keep serving the old head until it is invalidated or its lifetime expires. A generated preview image is worse: the consumer that fetched it caches it under **its** URL, on a schedule you do not control, so a corrected head can still unfurl with a stale image. The remedy is to key such a URL to the content — a hash or version in the path or query — so that a change produces a new URL the consumer has never seen. ## The design rule this suggests Before a head entry is allowed to carry volatile data, decide what will produce the page again when that data changes, and how quickly. If the honest answer is "nothing until the next release", the entry does not belong in the head of a prerendered route. That decision is cheaper made once, as a rule about what the head may contain, than repeatedly as a bug report about a preview that is out of date.

  • Why can a generated preview image stay stale even after the page is produced again?
    Because the consumer that fetched it caches it under its own URL, on a schedule you do not control, independently of your HTML. Key the image URL to the content — a hash or version in the path or query — so a change yields a URL that consumer has never fetched, and give the image route its own cache lifetime.
  • How does a regeneration window differ from an on-demand invalidation?
    A window is time-based: once it expires the next request makes the stored page eligible to be produced again, usually serving the existing copy meanwhile. On-demand invalidation is event-based: the system that changed the record drops that page explicitly, so the fix is prompt but every mutation path must fire the trigger.
  • How do you confirm the head is stale rather than the browser caching the page?
    Fetch the URL as a plain HTTP request, without executing scripts, and read the head in the returned bytes — that is what a non-executing consumer receives. Inspecting the live document in a browser proves nothing, because the client has already repaired what it renders.

A printed poster with a correction sticker applied at the door: visitors read the corrected text, but anyone who takes a copy from the stack gets the original.

saying these in an interview costs you the question

  • Thinks a client-side title update fixes what non-executing consumers see.
  • Assumes every deploy rebuilds every stored page regardless of build caching.
  • Believes the head can change without the stored HTML being produced again.
  • Forgets that a cache in front holds its own copy of the stale document.
  • Expects an unfurled preview image to refresh while its URL stays the same.
  • Diagnoses from the browser's rendered document instead of the served bytes.