Because content-hashed assets are never overwritten, every release leaves the previous build's files behind. How would you decide how long to keep old builds' assets available, and what does that number depend on?
answer
- retention is compatibility, not storage
- document lifetime plus open-tab tail
- rollback horizon sets a floor
- measure build age in field data
- shorten the tail, then retain less
basics
~20 sKeep old assets at least as long as any document naming them can still be served: HTML cache lifetime plus the open-tab tail, plus your rollback window. Measure that tail with field data rather than guessing.
solid answer
~60 sThe retention window is not a storage decision, it is a compatibility decision. Its floor is the longest time a client can still be running an old build's document — the document's freshness lifetime, plus any edge TTL, plus the tail of tabs that stay open — and it also has to cover however far back you might roll a release. I would not pick that number by intuition; I would measure it, by having clients report the build they are running and looking at the age distribution in field data, then set retention comfortably past the high percentile rather than the median. On the other side of the ledger, storage is cheap but not free of consequences: old bundles stay fetchable, old clients keep executing old code, and an unbounded pile has no owner. So I pair a generous window with an active mechanism to shorten the tail — an in-app notice that a new version is available — and an automated cleanup that never removes the current build or the last known good one.
go deeper
Know that a deploy adds a new set of hashed files rather than replacing the old ones, and that removing the previous build too early is what breaks users who are still on it.
Be able to state the floor as a sum — document freshness plus edge TTL plus how long a session can stay open — and explain why rollback also depends on the old build still being published.
Show how you would measure the client-age tail from field data and set the window past a high percentile, and argue for shortening the tail with an update prompt rather than only retaining longer.
Own the policy and its couplings: retention, document cache lifetime, and rollback horizon are one decision, expressed as keep-younger-than-T-and-at-least-N-builds, automated, and revisited whenever any of the three moves.
## Why this becomes a real decision Immutable, content-addressed assets accumulate by design. Nothing is overwritten, so every release adds a full set of files and removes none. That is a feature — it is exactly what lets two builds coexist while clients migrate — but it means someone eventually has to answer: when is it safe to delete a build? Getting it wrong in one direction produces broken pages for real users; getting it wrong in the other produces a directory nobody understands, a slow deploy listing, and a growing set of URLs still serving code you would rather nobody ran. Neither failure is dramatic enough to be noticed early, which is why the policy tends to be set by accident. ## The floor: how long can a client still name these files? Retention must exceed the maximum lifetime of any document that references the build. That is a sum, not a single number: - the freshness lifetime you serve on the document, - any additional TTL held by intermediate or edge caches, - the tail of sessions that keep an old document alive in memory — a single-page app in a pinned tab can run for days, - plus the rollback horizon: if you might revert to the release from three days ago, that release's assets must still be published, or the rollback restores a document whose files are gone. The first two you control directly and can compute. The third is behavioural and is the one that surprises teams, because no header touches it. ## Measuring the tail instead of guessing The honest way to size this is field data. Embed the build id in the application and have your monitoring report it, or attribute asset requests to the build they belong to, and then look at the distribution of *build age at request time*. You will typically see a steep drop within the first hour and a long, thin tail. Set retention past a high percentile of that tail — the point of the exercise is the tail, so the median tells you nothing. That measurement also gives you something better than a bigger number: it tells you whether the tail is worth attacking directly. If a meaningful share of traffic is running week-old builds, the answer is not a year of retention, it is a version check in the application that prompts those users to reload. Shortening the tail is cheaper and safer than storing forever, and it has an independent benefit — those users are also missing every fix you have shipped since. ## The costs on the other side Storage is genuinely cheap, so the real arguments against keeping everything are different: - **Old code stays reachable.** Anyone with the URL can fetch a bundle from a build you have since patched, and more importantly some users are still *executing* it. That is a client-tail problem rather than a hosting problem — deleting the file does not stop the tab that already loaded it — but it belongs in the conversation with security review, and it is another argument for actively converging clients. - **Operational drag.** Very large asset directories slow deploys, listings, and syncs, and make it harder to see what is actually live. - **No owner.** An unbounded directory with no policy is a decision nobody made, which means the day someone finally cleans it up is the day the outage happens. ## The shape of a defensible policy Express it as a rule with a floor and a safety net, not as a single number: keep every build younger than *T*, and always keep at least the last *N* builds regardless of age, so a quiet period does not leave you with only the current release when you need to roll back. Never delete the currently deployed build or the last known-good one. Automate the cleanup so it is not a manual chore, and make it dry-run first. Derive *T* from measured client age rather than from a comfortable-sounding duration, and revisit it when you change the document's cache lifetime — those two numbers are joined, and changing one without the other is how this quietly breaks. ## The judgment being tested The interesting part is not the number; it is recognising that the number is downstream of decisions made elsewhere. Cache the document longer and you must retain longer. Ship an update prompt and you may retain less. Promise fast rollbacks across a week and you have set a floor. A good answer connects those levers and says which one you would rather move, instead of asserting "keep thirty days" as if it were a constant.
- Does keeping old bundles published create a security problem?It keeps patched code fetchable by URL, which is worth reviewing, but the sharper risk is clients still executing an old build — and deleting files does not stop a tab that already loaded them. The right control is converging clients faster with a version check and update prompt, plus not treating a long retention window as a substitute for shipping fixes. Delete only when no live client can still need the files.
- What would you measure to justify the number rather than asserting it?The age of the build a client is running at the moment it requests something — reported through a build id in your field monitoring. Plot the distribution and read the tail, not the median. That single chart sets the retention floor, tells you whether an update prompt would pay for itself, and gives you a way to notice when a change to the document's cache lifetime has moved the tail.
- How does this policy interact with the document's cache lifetime?They are the same decision seen from two sides. Every extra minute of document freshness is an extra minute during which clients can still name the previous build's files, so it pushes the retention floor up. If someone proposes caching the document longer to cut origin load, the cost is not only staleness — it is a longer, more expensive retention obligation, and that should be stated in the same discussion.
saying these in an interview costs you the question
- Deletes the previous build as part of every deploy
- Says storage is cheap, so keep everything forever
- Ignores tabs open across multiple releases
- Picks a round number with no measurement behind it
- Forgets that rollback needs the old build published