Why can a visitor arriving after a prerendered page is considered stale still be served the old HTML, and who gets fresh?
answer
- two clocks, not one
- due for refresh, not withheld
- the request that notices pays nothing
- fresh HTML lands after the swap
basics
~20 sBeing stale marks a copy as due for refresh; it does not withhold it. The request is still answered from storage, and the fresh HTML first reaches whoever arrives after the out-of-band render has completed and replaced the copy.
solid answer
~40 sStaleness in this model is an instruction about *refreshing*, not about *serving*. When a request finds the stored copy past its freshness point, the copy is still what gets sent — immediately, unchanged — while a render of that path proceeds outside the response. The new HTML becomes visible only after that render finishes and the stored copy is replaced, so the first visitor to see it is one who arrives afterwards. This is the most-missed detail of the model: candidates reason that a freshness window of `N` seconds means nothing older than `N` seconds is ever served, when the window really says when a refresh becomes due, and the served age is that window *plus* the render's own duration. Becoming due changes the copy's future, not the response in hand.
go deeper
Hold on to one sentence: a page marked stale is still the page you get. The newer version shows up on a later visit, once a refresh has finished somewhere behind the scenes.
Separate the two clocks in your answer — the window that makes a copy due for refresh, and the render duration that decides when the replacement actually appears. The served age is both of them together, not just the first.
Turn it into operational language: the system guarantees eventual freshness, so quote a typical age and a worst case rather than a maximum, and verify refresh behaviour with two requests instead of one.
Make the distinction explicit in the product contract. A freshness window configured by an engineer reads to stakeholders as a guarantee of maximum age; state the real guarantee before someone else discovers it in an incident.
## Two different clocks There are two independent measurements in this model and conflating them is the classic error. - **The freshness clock** measures how long a stored copy is treated as good enough. When it runs out, the copy is *due for refresh*. - **The render clock** measures how long producing a replacement actually takes — data access, component execution, HTML serialisation. A visitor's experience is governed by neither clock on its own. The response they get is governed by **what is in storage at the instant their request is handled**, and that is the older copy until a render has completed and published its output. ## Why being due does not withhold the copy The whole point of refreshing out of band is that the response path stays cheap. If a request that noticed the staleness were held until a fresh render finished, that request would cost exactly what rendering inside the request costs — and the model would have bought nothing. So the framework does the opposite: 1. It answers from the stored copy, immediately, with no data access. 2. It arranges for a render of that path to happen outside that response. 3. It replaces the stored copy when that render completes successfully. 4. It answers subsequent requests from whatever is stored at that later moment. Steps 1 and 3 are not ordered with respect to each other by anything the visitor can observe. From the request's point of view, the refresh might as well not exist. ## Who actually receives the fresh HTML The first recipient of a refreshed page is **whoever requests that path after the replacement has happened**. Concretely, that means: - The visitor whose request found the copy due is served the old page. - Any visitor arriving during the render is served the old page. - The next visitor after the swap gets the new one — and so does everyone after them, until the copy is due again. An editor who publishes a change and reloads the page is almost guaranteed to see the old version on the first reload and the new one on the second. Interviewers use exactly this scenario because it separates candidates who have internalised the mechanism from those who have memorised a label. ## What the age you serve is actually made of | Contributor | Effect on the age of what is served | |---|---| | The freshness window | Sets the earliest moment a refresh becomes due | | The render's own duration | Extends the served age past the window by however long the render runs | | Renders that do not complete | Holds the old copy in place until one succeeds | | Long gaps between requests for a path | Leaves a copy sitting at whatever age it reached | So "the page is never more than a minute old" is not a claim the model supports. "The page becomes eligible for refresh after a minute, and is replaced shortly after a successful render" is. ## Why this detail matters beyond trivia - **Product expectations.** Anyone told the page refreshes every minute will report the first stale reload as a bug. Saying "the first request after the window still gets the old page" up front prevents that ticket. - **Verification.** A test that asks for a page once after the window and asserts fresh content will fail intermittently for the right reason. Ask twice, or assert on the stored copy rather than the response. - **Sizing.** Because refresh work is triggered by demand for a path rather than by views, render load tracks how many distinct paths become due — not how many people look at them. ## Where frameworks differ Frameworks vary in how forgiving they are about age: some will serve a stale copy indefinitely while refreshes keep being attempted, while others treat a copy beyond some larger bound as unusable and hold the request for a render instead, accepting the latency rather than serving very old HTML. Some publish the replacement to a single place every server instance reads; others refresh per instance, in which case two visitors can be served copies of different ages at the same moment. When you are asked what a visitor gets, the safe answer names the invariant — the response is served from storage, the render lands afterwards — and then says which of those variations the system in question chose.
- If the freshness window is one minute, is the served page ever older than a minute?Yes, routinely. The window says when a refresh becomes due; the served copy keeps answering while the render runs, so its age is the window plus the render duration. If renders fail, or nothing asks for the path, it can sit much older than that. Treat the window as an eligibility threshold, not a maximum age.
- How would you write a test that proves a page was refreshed?Do not assert on a single request after the window — that request is expected to return the old copy. Request the path, wait for the refresh to complete, then request it again and assert the new content; or observe the stored copy directly. Asserting once is the test that fails for the right reason and gets marked flaky.
- Why is this the detail candidates most often get wrong?Because the configuration reads like a maximum age, and the phrase "stale" suggests something unusable. In this model stale means eligible for replacement, and unusable is not what it means — the copy stays in service throughout. The mental model has to separate what governs the response from what governs the stored copy's future.
saying these in an interview costs you the question
- Thinks a stale copy is discarded and the request rendered fresh.
- Expects the request that finds the copy due to get new HTML.
- Says a stale response carries an error status or a redirect.
- Assumes the refresh completes within the same response.
- Claims the served page is never older than the freshness window.