skip to content

A rebuild of an old release fails because a package version is no longer in your Azure Artifacts feed, though nobody deleted it by hand. What in the feed's configuration explains this, and how do you recover?

level: seniorimportance: nice to knowfreq 28%

answer

  1. retention prunes per-package versions
  2. recency window spares active packages
  3. promoted versions are exempt
  4. recycle bin holds 30 days
  5. rebuild is not the same artifact

basics

~20 s

The feed's retention policy pruned it. Retention keeps a maximum number of versions per package and spares recently downloaded ones, so a version an old release pins can age out. Recover it from the feed's recycle bin, then promote versions you must keep to a view.

solid answer

~50 s

Feed settings carry a **retention policy** with two levers: a maximum number of versions to keep per package, and a window that spares packages downloaded recently. When a package accumulates versions past the maximum, the oldest that are not recently downloaded are deleted — including versions saved from upstream sources. A release that nobody has rebuilt for a year is exactly the profile that gets caught, because nothing downloaded it recently. Deleted packages land in the feed's **recycle bin**, where an Owner can restore them for 30 days; after that they are gone and, for an internal package, the only path back is rebuilding and republishing. The durable fix is the one the product intends: versions **promoted to a view** are exempt from retention deletion, so anything a supported release depends on should be promoted rather than left sitting in `@local`.

go deeper

for a junior

Know that a feed can be configured to delete older package versions automatically, and that deleted packages sit in a recycle bin for a while before they are gone for good.

for a middle

Explain the two retention levers — maximum versions per package and the recent-download window — and how they combine to delete versions that are both surplus and unused.

for a senior

Connect the setting to the delivery risk: an old release loses its dependency, rollback now depends on a rebuild, and the intended fix is promoting shipped versions to a view so they are exempt.

for a principal

Own the policy across feeds — what retention buys in storage versus what it costs in rollback confidence, and how promotion is made an automatic part of every release rather than a habit teams are asked to remember.

## Why feeds need retention at all A CI pipeline that publishes on every merge produces versions at the rate of the team's merge rate. Within a year an actively developed library can hold thousands of versions, almost all of which nothing will ever request again. Retention exists to stop a feed becoming an unbounded, unreviewable pile — and because storage above the included quota is billable. ## What the policy actually does Retention is configured per feed, in feed settings, with two inputs: - **Maximum number of versions per package.** The count of versions to keep for each package. Versions beyond that count become candidates for deletion, oldest first. - **Days to keep recently downloaded packages.** A protection window: a version that has been downloaded within that window is spared even if it is over the count. The two work together. A version is deleted when it is both surplus to the version cap *and* has not been downloaded inside the protection window. That combination is why the failure is so specific: it hits versions that are old **and** unused, which describes precisely the dependency of a release nobody has rebuilt lately. Retention applies to packages saved from upstream sources too. They are ordinary feed packages once saved, so a public dependency your old release pins can vanish from the feed the same way — though in that case a restore can usually re-save it from upstream, provided the version still exists publicly and the identity has Collaborator. ## The exemption that is the real answer **A version promoted to a view is not deleted by retention.** This is the mechanism the product provides for "keep this one forever", and it is the reason promotion and retention belong in the same conversation. The intended discipline is: - CI publishes freely into the feed; those versions are churn and are allowed to age out. - Anything that ships — anything a supported release, a customer deployment, or a downstream team depends on — is promoted to `@release` as part of the release flow. - Retention then prunes only the churn, and the promoted set is stable by construction. A team that never promotes anything is asking retention to distinguish important versions from noise using download recency alone, which it cannot do well. ## Recovering when it has already happened 1. **Check the recycle bin.** Deleted packages are retained there for 30 days and a feed Owner can restore a version from it. Inside that window this is a two-minute fix. 2. **Past 30 days, for an upstream-saved package**, request the version again: if it is still on the public registry and the identity has at least Collaborator, the feed re-saves it. Your build recovers without anyone republishing. 3. **Past 30 days, for an internal package**, there is no recovery of the original bytes from the feed. You rebuild from the tagged source and republish — which is only possible if the source tag, the toolchain, and the transitive dependencies are all still reproducible, and that is exactly the assumption an old release quietly falsifies. Step 3 is the one to talk about in an interview, because it exposes the real lesson: retention turned a storage setting into a delivery risk. The artifact you deployed is the artifact you should be able to redeploy, and if it can be pruned, rollback depends on a rebuild that may no longer produce the same bytes. ## Configuring it sensibly - Set the version cap generously for packages other teams consume; the storage saving from an aggressive cap is small compared with a broken rollback. - Make promotion part of the release pipeline, not a manual afterthought, so the exemption is applied by the same step that declares a version shipped. - Review the policy after enabling it on a feed that already has history — the first run can delete a great deal at once, and the recycle-bin window is the only safety net. - Do not lean on retention as a security control. It removes old versions; it does not remove a bad one, and unlisting or deleting a specific compromised version is a separate, deliberate act.

  • How do you stop this from happening to versions a supported release depends on?
    Promote them to a view as part of the release pipeline. Versions promoted to a view are exempt from retention deletion, so the act that declares a build shipped is also the act that makes it permanent — no separate list of protected versions to maintain and forget.
  • Does retention also delete packages that were saved from an upstream source?
    Yes — once saved they are ordinary feed packages and are pruned by the same rules. The difference is recovery: if the version still exists on the public registry, requesting it again re-saves it, so an upstream-saved package is usually recoverable where an internal one is not.
  • Why is rebuilding and republishing a poor substitute for recovering the original artifact?
    The rebuild is a new artifact. Transitive dependencies may have moved, the toolchain may have changed, and the output can differ from what was tested and deployed. If rollback depends on that rebuild, you are shipping something no one verified at the moment you can least afford a surprise.
  • Is retention a reasonable way to remove a compromised package version?
    No. Retention deletes old versions on a schedule based on count and download recency, which has no relationship to whether a version is dangerous. Removing a bad version is a deliberate act — unlist or delete it explicitly, and fix whatever pulled it in.

saying these in an interview costs you the question

  • Assuming nothing is ever deleted from a feed automatically
  • Thinking a downloaded-once package is protected forever
  • Not knowing promoted versions are exempt from retention
  • Treating a rebuild as equivalent to the original artifact
  • Believing deleted packages are unrecoverable immediately

context