· via dev.to (home feed)
npm, PyPI and crates.io expose no dependable signal for abandoned dependencies
A maintainer who normalises registry metadata found npm's deprecation flag is opt-in, PyPI's status classifier is typed once and never revisited, and crates.io offers only a timestamp.

A staleness column that could not become a verdict
A developer who maintains a tool that merges npm, PyPI and crates.io metadata into one row per dependency recently tried to answer a simple question: is this package abandoned? Writing on dev.to, they report that the attempt failed, and not because the data was missing. Each registry carries some hint of abandonment, and each hint is unreliable in its own way.
The tool already showed when a package was last touched. Converting that into a dead-or-alive flag turned out to be a different problem entirely, because the three registries do not agree on what abandonment would even look like.
npm: a deprecation flag that only fires when set
According to the dev.to post, npm has a deprecated field, a string attached to a specific version that a maintainer must set explicitly. When it is set, npm install surfaces a warning immediately. The author points to istanbul, which redirects users to nyc, and to jade (renamed pug) and gulp-util, all last published in 2015 and 2016, as cases where the field works as intended.
The failure mode is silence. Bower's last publish was in March 2022 and its own README declares the project unmaintained, yet the deprecated field was never set. A genuinely dead package looks identical to a healthy one unless someone with publish access remembers to act.
The post also highlights a subtler case: colors, the package at the centre of a 2022 supply-chain incident. The sabotaged versions 1.4.1 and 1.4.2 remain in the registry and can still be installed by exact pin, but the latest dist-tag was rolled back to 1.4.0 from 2019. A default install gets the pre-incident version, so the registry's tag history, not any status field, is what tells the story.
PyPI: a classifier typed once and never revisited
PyPI ships a Development Status classifier ranging from '1 - Planning' to '7 - Inactive', which sounds like exactly the signal needed. In practice, the author found, it is free text a maintainer types once, at whatever release they choose, and the registry has no mechanism that ever re-examines it.
The example given is nose, which last shipped in June 2015 and has been superseded by pytest for most of the intervening decade, yet still carries '5 - Production/Stable'. As a sanity check, the author looked at requests, which released a new version this year, and found the identical classifier. On this field, an actively maintained library and one untouched for eleven years are indistinguishable.
crates.io: the cleanest timestamp, and no opinion at all
The sparse index that cargo reads on every resolve carries no status concept whatsoever: no deprecation flag, no classifier, not even a homepage to check by hand. What it does have is a pubtime field, and the author nearly misread it. rustc-serialize 0.3.25 shows a publish time of December 2023, which looked like a migration stamp applied when the field was introduced. But crates.io's own documentation states that pubtime is backfilled without gaps and always holds the original publish date, and the version really was a bugfix shipped roughly eight years after the crate's heyday.
The net effect, per the post, is that the data is cleaner but the judgement is entirely yours: crates.io provides a precise, verifiable timestamp and says nothing about whether that timestamp should worry you.
Caveats the author is careful to flag
The post is candid about its limits. Nine hand-picked examples, chosen from packages whose status the author already knew, amount to an anecdotal sample rather than a survey, and the claim about PyPI's frozen classifiers rests on just two packages. The author plans to fold a normalised 'last touched' plus 'explicitly flagged' column into their Package Registry Scraper project, and has published a field-by-field cheatsheet under the name noble-ronin/package-staleness-data.
Why it matters
Abandoned dependencies are a real supply-chain exposure: unmaintained packages accumulate unpatched vulnerabilities and are prime targets when dormant maintainer accounts get compromised. If the registries themselves cannot distinguish a dormant package from a dead one, every consumer has to run their own heuristics, or fall back on download numbers and intuition, as the post suspects most developers do. Until a registry offers a maintained and periodically revisited status signal, 'last publish date, interpreted by you' remains the most reliable check available, and it is weakest exactly where maintainers have quietly walked away without leaving a note.
- #npm
- #pypi
- #crates-io
- #supply-chain
- #dependencies