skip to content

When a new release replaces the old one, which cached copies outlive the deploy, and what decides whether reusing them is safe?

level: seniorimportance: should knowfreq 55%

answer

  1. sort the copies by where they live
  2. only a replaced process is cleared
  3. old and new builds overlap during rollout
  4. build identity in the key prefix
  5. namespacing buys correctness, costs warmth

basics

~20 s

Anything inside a replaced process dies with it; anything outside survives, so a shared store and the cache in front keep serving copies built by the previous release. Reuse is safe only for entries that cannot differ between builds.

solid answer

~50 s

Sort the copies by where they live. Process memory goes away when the instance is replaced, so every new instance starts cold. A shared store is external and keeps every entry it held, including documents rendered by the old build. A cache in front keeps its stored responses, ageing on its own lifetime regardless of what was deployed. During a rolling release, old and new instances read and write the same shared store at the same time, so an entry can be written by one build and read by the other. Reuse is safe only if the entry's content is build-independent; if the markup, payload shape or referenced assets can change between builds, include a build identity in the cache key so the new release starts in its own namespace, and purge the cache in front for anything prerendered.

go deeper

for a junior

Remember that replacing instances only clears what was inside them. Caches that live outside the application keep serving what they already stored after the new version is live.

for a middle

Explain which store survives and why, and describe how a rolling release lets two builds share one cache at the same time. Know what putting a build identity in the key achieves.

for a senior

Own the release path: decide which entries are build-independent, namespace the rest, purge what sits in front of the app, and plan for the cold fleet that follows.

for a principal

Trade correctness against warmth explicitly. Decide which routes justify pre-warming, how long previous namespaces are retained for rollback, and who verifies the first requests after a release.

## Sort the copies by where they live Deployment is the moment when the question *where do these bytes live* pays off, because the answer decides survival: | Where a copy lives | Fate on deploy | |---|---| | Memory of a replaced instance | gone; the new instance starts cold | | A store shared by the instances | untouched; entries written by the old build remain | | A cache in front of the application | untouched; responses keep ageing on their own lifetimes | | A visitor's browser | untouched; bounded only by the headers already sent | Only the first row is cleared by the act of deploying. Everything else is exactly as it was a second before the release, which is the root of every post-deploy staleness report: a release does not invalidate anything it does not own. ## Two distinct hazards **Reuse across builds.** A stored document, or a stored piece of data, was produced by code that no longer runs. If the new build renders the same route differently, or expects a different payload shape, or references filenames the old build emitted, then serving the old entry is serving the old release. The visible consequences on a client that has already loaded are the province of release-skew handling; the cache question upstream of that is simply whether an entry from build N may be handed to build N+1 at all. **The overlap window.** A rolling release runs both builds at once, deliberately. If both read and write one shared store, then for the length of the rollout an entry written by either build may be read by the other, in both directions. A scheme that only clears the store at the start of the deploy does not survive this, because the old instances immediately write more old entries. ## Making the decision explicit 1. **Decide per class of entry whether it is build-independent.** A cached response from an upstream service usually is: it is data, not markup, and the new build reads it the same way. A rendered document usually is not. 2. **Put a build identity in the key prefix for anything build-dependent.** Each release then reads and writes its own namespace. Old entries become unreachable rather than dangerous, the overlap window is harmless because each build sees only its own writes, and a rollback finds its own entries still there. 3. **Accept the cold start that follows.** A namespaced release begins with nothing cached, so the first requests after a deploy pay full render cost and several instances may miss the same entry at once. If that is too expensive, warm the important routes deliberately rather than reusing entries you cannot vouch for. 4. **Clean up the previous namespaces.** Keyed-by-build entries accumulate; either give them a lifetime or remove them once a rollback is no longer plausible. 5. **Purge the cache in front for anything prerendered by the build.** Nothing about deploying removes those responses, and their lifetimes were chosen for performance, not for release timing. ## The copy you cannot touch at all A browser holding a response is outside every mechanism above. No release, no store purge and no removal from the cache in front reaches it; it expires when the lifetime the response already carried runs out. That is the reason release planning and caching policy are the same conversation: a generous lifetime sent yesterday is a constraint on what a deploy can correct today. ## The shape of a good answer Say where each copy lives, say that only process memory is cleared, and then treat the shared store and the cache in front as two things the release has to act on deliberately. Name the overlap window during a rolling release as the reason that a one-shot clear at the start of the deploy is not enough. Then make the trade-off visible: build-namespaced keys buy correctness at the cost of a cold fleet, so the interesting engineering is deciding which entries genuinely need it and pre-warming the handful of routes where a cold start would hurt. ## What the sloppy version sounds like That a deploy clears the cache. It clears exactly one cache, the one that was never shared in the first place, and leaves untouched the two stores that visitors are actually served from. The second-sloppiest version is clearing the shared store at the start of the rollout and calling it done, which ignores that the previous build is still serving and still writing for the length of the rollout.

  • Why is clearing the shared store when the deploy starts not sufficient?
    Because a rolling release keeps the previous build serving while the new one comes up, and it goes on writing entries into the store it was just cleared from. By the time the rollout finishes, the store holds a mixture again. Namespacing keys by build is what makes the overlap harmless, since each build only ever reads its own writes.
  • Which cached entries are usually safe to carry across a release?
    Entries whose content does not depend on the build: responses fetched from upstream services, and other data the new code reads the same way as the old. Rendered markup is the opposite case, since its output, its embedded asset references and its structure all move with the build. When in doubt, treat an entry as build-dependent, because the failure is user-visible and the cost is a cold start.
  • What is the cost of namespacing cache keys per build, and how do you soften it?
    Every release starts with an empty cache, so the first requests pay full render cost and several instances can miss the same entry simultaneously. Soften it by warming the routes that matter right after the release, by limiting concurrent identical renders so one miss does not become many, and by keeping genuinely build-independent entries outside the namespaced prefix.

saying these in an interview costs you the question

  • Saying a deploy clears the cache, without asking which one
  • Assuming a shared store is emptied when instances are replaced
  • Clearing the shared store once at the start of a rolling release
  • Reusing rendered markup across builds because the route is unchanged
  • Forgetting that prerendered responses stay stored in front of the app
  • Namespacing every entry per build and then being surprised by cold-start load