skip to content

What does deprecating a published npm version do, and how does that differ from unpublishing it?

level: juniorimportance: must knowfreq 62%

answer

  1. one is a message, one is removal
  2. the install still succeeds
  3. nothing is deleted, nothing breaks
  4. registries fence the destructive one
  5. reversible by clearing the message

basics

~20 s

Deprecating leaves the version fully installable and only attaches a message the registry shows at install time. Unpublishing removes the version so it can no longer be downloaded. One is a signal, the other is a withdrawal.

solid answer

~50 s

Deprecation is metadata, not removal. You attach a message to a version or a version range, the registry serves it alongside the package, and clients print it as a warning during install. Nothing is deleted, no build breaks, and anything already resolved keeps working exactly as before. It is also reversible — clearing the message un-deprecates the version. Unpublishing is the destructive option: the version's files stop being served, so a fresh install of that exact version fails. Because that breaks strangers' builds, registries constrain it heavily — npm allows a clean unpublish only in a narrow window right after publication, and afterwards effectively only when nothing depends on it. Some registries do not offer it at all: a release published to Maven Central is immutable, so the only move there is to publish a new version and advertise it. Deprecation is the tool you reach for in almost every case; unpublish is for artifacts that must not exist.

go deeper

for a junior

Be ready to state the difference in one line: deprecation attaches a warning message and removes nothing, unpublishing takes the version away. Know that deprecating never breaks an install.

for a middle

Explain the mechanics — the message is registry metadata served with the package, it accepts a version range, and it is reversible. Also explain why registries restrict unpublish so tightly and why some, like Maven Central, forbid it outright.

for a senior

Show the operational judgment: deprecation is a courtesy in a log nobody reads, so pair it with a published advisory keyed to the affected range, and publish the fixed version before you flag the bad one so consumers have somewhere to go.

for a principal

Own the stance that publishing is effectively irreversible and design the release process accordingly — immutable identifiers, an advisory channel that reaches consumers automatically, and deletion reserved for artifacts whose existence is itself the hazard.

## Three different verbs, three different promises Once a version is public, strangers can resolve it. Everything you can still do to it falls into one of three buckets, and mixing them up is the most common confusion in this area. **Deprecate — a signal, attached to a version that stays.** You supply a message and a version selector; the registry stores that message against every matching version and serves it in the package metadata. Install clients surface it as a warning line. The tarball is untouched, the checksum is unchanged, resolution behaves identically, and a build that would have succeeded before still succeeds. It is purely advisory, and it is reversible: setting the message to an empty string removes the deprecation. **Yank (crates.io, and PyPI's equivalent) — withhold from future selection, delete nothing.** A yanked version stops being an eligible candidate for new dependency resolution, but the files remain downloadable and anything that already pins the exact version keeps working. It sits between the other two: stronger than a warning, weaker than removal, and also reversible. **Unpublish / delete — the bytes stop being served.** Only this one actually takes something away. A fresh attempt to download the exact version fails. ## Why deprecation is the usual answer A published version is an input to other people's builds. Removing it turns their working pipeline into a failing one, at a moment they did not choose, for a reason they have to go and discover. That is why registry policy fences unpublish so tightly. npm permits a straightforward unpublish only very soon after the version was pushed, and after that only under narrow conditions such as nothing depending on it; beyond that you are asking a human at the registry for an exception. On Maven Central, released coordinates are immutable by policy — the guarantee that a given group, artifact and version always maps to the same bytes is the whole point, and it is worth more to the ecosystem than your ability to retract a mistake. PyPI does let you delete files, with a catch covered below. So the honest mental model is: **publishing is close to irreversible, and your post-publication toolkit is mostly about signalling, not about recall.** ## What each one does to an existing lockfile This is the question interviewers actually use to test whether you understand the difference. | Action | Existing lockfile | New resolution | Files still downloadable | |---|---|---|---| | Deprecate | unchanged, installs fine | still selectable | yes | | Yank | unchanged, installs fine | not selected | yes | | Unpublish / delete | install of that version fails | not selectable | no | Notice that in two of the three rows a team already on the bad version is entirely unaffected. Nobody is emailed. Nothing is recalled. If your goal is for existing consumers to move, none of these three verbs achieves it on its own. ## The limit of a deprecation message as a security channel Deprecation warnings are read by roughly nobody. A real project's install output already carries deprecation lines from a dozen transitive packages it never chose, and the whole block scrolls past in a CI log. If you deprecate three minor versions of a widely used package because they carry a security flaw, you have added noise to a stream that was already ignored. That is not a reason to skip deprecating — it is cheap and it helps the person who does read it — but it means the message is a courtesy, not a notification mechanism. The channel that actually reaches consumers is a published security advisory keyed to the affected version range, because scanners and update bots consume advisory feeds automatically and open a change against affected projects. Registry-side flags reach only the people who happen to resolve fresh. ## Filename and version immutability A related rule catches people out: on PyPI a deleted filename can never be reused. The registry will not accept a re-upload of the same file name even after deletion, precisely so that a name a consumer or a mirror recorded can never later mean different bytes. Practically, that means "delete the broken file and re-upload a fixed one under the same version" is not available — you publish a new version number. Immutability of a published identifier is the property the whole verification chain depends on, and every registry protects it in some form. ## The reflex to build When a bad version is out: publish the fixed version first, so consumers have somewhere to go; deprecate or yank the bad one so new adopters do not land on it; publish an advisory so tooling tells the people already on it; and reserve deletion for artifacts whose mere existence is the hazard.

  • Does deprecating a version change anything for a build whose lockfile already resolved to it?
    No. The resolved version, the tarball and the checksum are all unchanged, so the install succeeds exactly as before. At most the client prints a warning line, and for a deep transitive dependency it may not even do that. If you need existing consumers to move, deprecation on its own will not achieve it.
  • Can you deprecate one specific version, or only the whole package?
    You pass a version range, so you can mark a single version, a set of minors, or every version of the package. The message is stored against each matching version and served in the registry metadata. Supplying an empty message clears the deprecation again, which makes it a safe, reversible action.
  • Your CI output already prints deprecation warnings from a dozen transitive packages. What does that do to the value of deprecating a version for a security reason?
    It largely destroys it. Deprecation warnings are ambient noise in a build log, so a security-motivated message competes with ones about renamed utility packages and lands the same way — unread. Deprecate anyway, because it is cheap, but treat a published advisory keyed to the affected version range as the channel that actually reaches consumers, since scanners and update bots act on it automatically.

Deprecating is a sticker on the shelf saying this model has a known problem. Unpublishing is taking the box off the shelf entirely — everyone who already carried one home still has it either way.

saying these in an interview costs you the question

  • Says deprecating removes the version from the registry
  • Assumes a deprecation warning fails the build
  • Thinks unpublish is available on any registry at any time
  • Treats a deprecation message as an advisory consumers will see
  • Believes deprecating changes what an existing lockfile resolves

context