How can requests from an already-loaded page be pinned to the build that served it, and what does that require of the hosting setup?
answer
- stamp, echo, route
- keep the old deployment addressable
- window must outlast a real session
- shared database still spans all pinned versions
- unknown identifier must reject, not fall through
basics
~20 sStamp a deployment identifier into each document, have the client echo it on every later request, and route on it to the retained older deployment. It needs old versions addressable, a drain window, and an expiry that forces a reload.
solid answer
~50 sPinning turns skew into a routing problem. The build stamps its deployment identifier into the document it serves; the client echoes that identifier on every subsequent route-data fetch and write, in a header, a query parameter or a cookie set at load; the layer in front of the app routes by it and sends those requests to the deployment that issued the page. That requires previous deployments to stay running and addressable for a drain window, which costs money and only works on targets that can host several versions at once — a plain file host can retain old assets but cannot pin server behaviour. Pinning also cannot cover shared state: one database, one cache, one third-party API serve every pinned version, so their contracts must satisfy all of them. And it must expire: past the window the server rejects the unknown identifier and the client hard-loads.
code
pseudocode · 17 lines// 1. the document served by deployment d7 carries its identity
render(document, { meta: { deploymentId: "d7" } })
// 2. every later request from that page repeats it
fetch(routeDataUrl, { headers: { "x-deployment-id": "d7" } })
// 3. the routing layer in front of the app dispatches on it
onRequest(req):
id = req.header("x-deployment-id")
if id is absent: forwardTo(current) // first document load
else if isRetained(id): forwardTo(deployment(id)) // pinned to its own build
else: respond(410, "unknown deployment")
// 4. the client turns the rejection into a full document load
if response.status == 410:
savePendingInput()
location.reload()go deeper
Understand the shape: the page remembers which build served it, sends that with later requests, and the infrastructure can route those requests back to that build.
Explain the three parts — stamping the identifier into the document, echoing it on every request, routing on it — and why the pin has to expire at all.
Show the operational reality: a drain window sized to real session length, stateless instances, an explicit rejection at expiry, and a database schema that all retained versions can read.
Decide whether to buy it. Weigh the running cost of several live versions and a widened migration-compatibility window against cheaper measures, and reserve pinning for long sessions with unsaved work.
## The idea Every other mitigation tries to make the new release tolerate an old client. Pinning does the opposite: it keeps the **old release** available and sends the old client back to it, so nothing is skewed at all until the session ends. The mechanism has three moving parts. 1. **Stamp.** The document a deployment serves carries that deployment's identifier — in the markup, in the embedded state, or as a cookie set on the document response. 2. **Echo.** Everything the loaded page does afterwards repeats it: route-data fetches, write submissions, and asset requests if the assets are not already content-addressed. A request header is the usual carrier; a cookie works too, but a cookie is per-browser, not per-tab, and so pins every tab in that browser together. 3. **Route.** The layer in front of the app — the CDN, the reverse proxy, the platform's router — reads the identifier and forwards to the matching retained deployment instead of the current one. ## What it requires | Requirement | Why | What it costs | |---|---|---| | Previous deployments still addressable | Nothing to route to otherwise | Several live versions: instances, functions, or at least their code kept warm enough | | A routing layer that can dispatch on a request attribute | The identifier must select a backend | Configuration at the edge, and a fallback for requests without one | | A retention window longer than a realistic session | A pin that expires mid-session is no better than no pin | Storage and running cost proportional to the window times the deploy rate | | Stateless application instances | An old version and a new one must be interchangeable behind shared state | Sessions, uploads and caches must not live in process memory | | An expiry path | The window has to end | A defined rejection response the client turns into a hard load | On a long-running-process target you keep the previous process alive and drain it. On a function platform each deployment is usually addressable already, and pinning is largely a routing rule. On a plain file host there is no server to pin — you can retain old asset files, which fixes missing chunks, and nothing more. ## What pinning cannot fix This is the part senior candidates are expected to raise unprompted. Pinning isolates **your application code**. It does not isolate anything shared: - **The database.** One schema serves every pinned version, so a migration still has to be compatible with the oldest version you keep alive. That is the real constraint, and it is why a long retention window is not free even when the instances are. - **Caches and regeneration stores.** A shared store written by the new version is read by the old one and vice versa; entries need keys that distinguish versions or shapes that both can read. - **Third-party and internal APIs.** They upgrade on their own schedule, oblivious to your pins. - **Anything the browser persisted.** Data an old client wrote into browser storage is read by a new client after the next load. So pinning converts a client-compatibility problem into a **data-compatibility** problem. That is usually a good trade — data contracts change less often than build identifiers — but it is a trade, not an elimination. ## Ending the pin A pin must expire, or you are running every release you ever shipped: 1. Retire deployments older than the window. 2. When a request arrives with an identifier that is no longer retained, answer with a defined "unknown deployment" response rather than silently falling through to the current release — falling through re-creates exactly the skew you were avoiding, at the least predictable moment. 3. The client treats that response as a signal to perform a full document load, preserving any pending input first. ## When it is worth it Pinning is the heavyweight option. A cheaper stack covers most of the pain: retain the previous builds' hashed assets, keep old write-handler mappings answerable, change payload shapes additively, and make the client hard-load when it detects that it is out of date. Reach for pinning when sessions are long and interactive, when a mid-session failure is expensive (checkout, an editor, anything with unsaved work), and when the platform already gives you addressable deployments so the incremental cost is a routing rule rather than a second fleet.
- Why must an unknown deployment identifier be rejected rather than quietly served by the current release?Falling through re-introduces skew at the worst moment: the client believes it is pinned, so it has no reason to suspect the response came from a different build. An explicit rejection is a signal the client can act on with a full document load, which is the only thing that actually resolves the mismatch.
- What is the hardest constraint that pinning does not remove?Shared state. Every pinned version talks to one database, one cache and the same external services, so a schema or contract change must remain readable by the oldest retained version. Your retention window is therefore also the compatibility window your migrations must honour.
- Why is a cookie a flawed carrier for the deployment identifier?A cookie is scoped to the browser, not the tab. Loading a second tab updates it, silently repinning tabs that are still running an older client, and a shared cookie cannot represent two tabs on two different deployments at once. A header set by the page that echoes its own stamped identity keeps the pin per-document.
saying these in an interview costs you the question
- Claims pinning removes the need for compatible database migrations
- Falls through to the current release when the identifier is unknown
- Sets a retention window shorter than a typical session
- Assumes a plain static file host can pin server behaviour
- Keeps every past deployment alive with no expiry policy
- Stores session or cache data in instance memory while running several versions