Data IntelligenceOriginal ResearchOpen SourceDeveloper ToolsApify

8 of 136 Most-Depended-On OSS Packages Are Abandoned

ApifyForge audited 136 npm/PyPI/cargo packages. 8 (5.9%) are silent 365+ days. moment.js (47,978 stars), request, prop-types — the named cohort.

Ryan Clinton

The problem: Open source maintenance is one of the most consequential, least measured signals in the software supply chain. We talk about maintainer burnout in abstract — Linux Foundation surveys, xkcd 2347, the occasional viral resignation post — but the question that matters operationally is simpler: which named packages, right now, in the dependency graphs of millions of production codebases, have nobody behind them? A 2026 ApifyForge audit captured the answer for 136 of the most-depended-on packages on npm, PyPI, and crates.io.

What is the OSS Maintainer Burnout Index? A 2026 ApifyForge audit of 136 most-depended-on packages across npm, PyPI, and crates.io found 8 (5.9%) with no maintainer activity in over 365 days, and 12 (8.8%) silent for 180+ days. The named at-risk cohort includes moment.js (47,978 stars, 632 days silent), request (25,565 stars, 632 days, deprecated), facebook/prop-types (4,454 stars, 721 days, archived), structopt (2,727 stars, 851 days), and lazy_static (2,030 stars, 464 days). Two are explicitly archived on GitHub yet remain in production dependency graphs.

Why it matters: The npm and crates.io ecosystems show identical 8% abandonment rates among foundational packages — Rust's safety reputation does not extend to maintenance-stage longevity. PyPI's at-risk packages cluster in the 180-365 day stale window rather than the abandoned tier, and concentrate in the Pallets ecosystem (Jinja2, MarkupSafe alongside PyYAML), illustrating how small-maintainer-cohort dynamics slow multiple foundational packages in lockstep.

Use it when: reporting on software supply chain risk, citing named-package evidence for OSS-sustainability coverage, briefing security or platform-engineering teams on dependency-graph silent-tail risk, or sourcing a reproducible quantitative anchor for a feature on open source maintenance economics.

Key findings

  • 136 most-depended-on packages audited across npm (50), PyPI (36), and crates.io (50), captured 8 May 2026.
  • 8 packages (5.9%) have been silent for over a year — the audit's "abandoned" threshold.
  • 12 packages (8.8%) are silent for 180+ days when the stale tier is included.
  • 2 packages are explicitly archived on GitHub yet still ship in production dependency graphs: facebook/prop-types and bincode-org/bincode.
  • moment.js leads the abandoned cohort by stars at 47,978, with 632 days since last commit and an explicit "maintenance mode" status from the project itself.
  • npm and crates.io show identical 8% abandonment rates among foundational packages; PyPI's at-risk slice clusters at 180-365 days rather than the >365-day tier.

In this article: Quick answer · The 12-package leaderboard · Per-ecosystem breakdown · moment.js · request · The two archived · The Rust paradox · Pallets in lockstep · Methodology · Caveats · FAQ

Quick answer

  • What it is: A 136-package audit of GitHub maintainer activity for the most-depended-on packages on npm, PyPI, and crates.io, captured 8 May 2026.
  • Sample: Top 50 most-depended-on packages on npm, top 50 on crates.io, plus 36 of the top 50 on PyPI (14 PyPI packages were excluded — see methodology).
  • Source: ApifyForge's github-repo-search Apify actor in mode: "dependency-audit" with enrichRepoData: true, fed by registry-resolved repo URLs from bash scripts/ms research oss-burnout-index.
  • What "abandoned" means in this audit: zero pushes to the repo's default branch in 365+ days. It is a behavioural label, not a quality verdict.
  • Main caveat: A package can be feature-complete and stable while showing zero activity. moment.js's silence is a deliberate maintenance-mode posture, not neglect. Coverage should disclose the difference.
PackageDays silentStarsStatusEcosystem
moment63247,978Maintenance modenpm
request63225,565Deprecated 2020npm
prop-types7214,454Archivednpm
structopt8512,727Superseded by clapcargo
bincode2663,074Archivedcargo

What is OSS package abandonment?

Definition (short version): OSS package abandonment is the behavioural state where a published software package on a public registry (npm, PyPI, crates.io) has received no maintainer activity — measured by pushes to its default branch on GitHub — for a defined silence threshold, while remaining listed and installable from the registry it was originally published to.

The label "abandoned" in this audit specifically means zero pushes to the repo's default branch in 365+ days. It captures activity, not quality. A stable, feature-complete package that does its job correctly will show up as abandoned under this definition; so will a project whose maintainer has burned out and walked away. The data does not distinguish between the two cases. That distinction has to come from supplementary signals — a maintenance-mode notice, an archive flag, a deprecation issue, a successor package.

The broader pattern of declining OSS maintainer engagement is documented in the Linux Foundation's 2024 Open Source Software Maintainer report and corroborated by survey work from Tidelift and the Open Source Security Foundation. This audit is narrower: a specific behavioural snapshot of a specific package cohort on a specific date.

Also known as: package staleness, repository dormancy, dependency rot, OSS supply-chain silent-tail, foundational-package neglect, maintainer activity collapse.

The 12-package at-risk leaderboard

Sorted by days silent, descending. Captured 8 May 2026 via the github-repo-search Apify actor.

Days silentStarsArchivedEcosystemPackageRepo
966199npmmkdirpisaacs/node-mkdirp
8512,727cargostructoptTeXitoi/structopt
7214,454ARCHIVEDnpmprop-typesfacebook/prop-types
63247,978npmmomentmoment/moment
63225,565npmrequestrequest/request
4931,499cargowalkdirBurntSushi/walkdir
4642,030cargolazy_staticrust-lang-nursery/lazy-static.rs
4294,027cargodashmapxacrimon/dashmap
32711,620pypijinja2pallets/jinja
2663,074ARCHIVEDcargobincodebincode-org/bincode
2242,888pypipyyamlyaml/pyyaml
223688pypimarkupsafepallets/markupsafe

The 8 packages above the bold-line threshold (>365 days) are formally abandoned by the audit's definition. The 4 below (180-365 days) are stale.

Aggregate stats:

  • 8 of 136 packages (5.9%) are abandoned (>365 days).
  • 12 of 136 packages (8.8%) are at-risk (>180 days).
  • Combined GitHub stars across the 8 abandoned packages: 88,479.
  • Two packages are formally archived on GitHub: prop-types and bincode.
  • Five abandoned packages have more than 1,000 GitHub stars.
  • The largest abandoned package by star count (moment.js) has 47,978 stars and remains a transitive dependency in millions of npm projects.

Per-ecosystem breakdown

EcosystemAuditedAbandoned (365+d)Stale (180-365d)Low activity (90-180d)Active (<90d)Archived
npm504 (8.0%)04411
PyPI36031320
cargo504 (8.0%)12431
Total1368 (5.9%)4 (2.9%)7 (5.1%)116 (85%)2 (1.5%)

The npm and Cargo ecosystems show identical abandonment rates. PyPI's foundational packages show zero year-plus-silent — its at-risk slice is concentrated in the 180-365 day window (Jinja2, PyYAML, MarkupSafe), three projects collectively used in tens of millions of installs.

The headline cross-ecosystem finding is the npm/cargo parity. Rust's developer-survey reputation for safety has led the Stack Overflow developer rankings for nine consecutive years. That reputation does not extend to maintenance-stage longevity. The same share of foundational packages goes silent on cargo as on npm.

Story A — moment.js: the dead library everyone still uses

StatValue
GitHub stars47,978
Days since last push632
StatusMaintenance mode (per project's own statement)
Ecosystemnpm

moment.js is the largest package in the abandoned cohort by every footprint proxy available — stars, transitive dependents, recognition. The maintainers publicly state on momentjs.com that the project is in "maintenance mode" and recommend day.js, luxon, or date-fns as alternatives.

The 632-day silence isn't neglect. It's a deliberate maintenance-mode posture. The maintainers made an explicit decision: the library is feature-complete, the date-and-time problem space has matured, and contributing energy to a successor (or recommending one) is more useful than continued patching. That's a defensible engineering judgement.

The downstream consequence is the same regardless of intent. moment is pulled in as a transitive dependency wherever a single library in the chain hasn't migrated. Tens of thousands of production codebases ship a date library their original authors have publicly recommended against using. The package isn't "dead" in any moral sense, but the operational fact — that it's foundational to the npm dependency graph and receives no commits — is the data point that matters for supply-chain risk modelling.

Story B — request: deprecated, dead, still installed

StatValue
GitHub stars25,565
Days since last push632
StatusOfficially deprecated 2020
Ecosystemnpm

request is the canonical example of an OSS package that was explicitly killed by its maintainers but kept alive by inertia. The maintainers wrote a detailed deprecation notice in 2020 recommending alternatives — axios, node-fetch, got. Five years later the package still has 632 days of zero activity AND a top-1000 npm dependency footprint, because legacy packages high in the dependency tree still pin to it.

This is the second most-cited node module's deprecation story (after the left-pad incident of 2016). The lesson it teaches is the same one the moment.js story teaches: a maintainer's decision to stop maintaining a package does not retroactively remove it from anyone's dependency graph. Migration is a downstream-consumer choice that doesn't happen automatically and often doesn't happen at all.

Story C — The two archived packages still in the dependency graph

PackageStarsDays silentStatus
facebook/prop-types4,454721ARCHIVED
bincode-org/bincode3,074266ARCHIVED

Archived on GitHub means the maintainer has explicitly ended the project. The repo becomes read-only. New issues cannot be filed; pull requests cannot be merged. It is the strongest "do not use this" signal a maintainer can produce short of unpublishing from the registry — which neither prop-types nor bincode has done.

Both packages remain in active use as direct dependencies of foundational frameworks. prop-types ships with React (where it was carved out as a standalone package in React 15.5 in 2017 and is still installed wherever older React patterns are used). bincode is in the Rust binary-serialization ecosystem alongside serde, used in production at companies including Discord, Mozilla, and Cloudflare per public engineering blog posts.

The archive flag is documentation of an organisational decision. It does not retroactively migrate downstream consumers. Both packages will continue to ship in production codebases for years.

This is the structural pattern documented in the GitHub repository abandonment detection guide — the abandonment signal exists in public metadata; downstream adoption of that signal is a separate, slower process.

Story D — The Rust paradox: 4 of 50 foundational crates abandoned

Cargo (Rust) shows 4 of its 50 most-used crates abandoned (>365 days):

CrateStarsDays silentRole
structopt2,727851CLI argument parsing (predecessor to clap)
walkdir1,499493Filesystem traversal
lazy_static2,030464Lazy-initialised statics
dashmap4,027429Concurrent hashmap

Two of these have natural successors. structopt was superseded by clap v3+'s derive macro feature — the original maintainer of structopt became a clap maintainer, and the migration story is well-documented. lazy_static has been substantially replaced by OnceLock (in the Rust standard library since Rust 1.70) and once_cell. The other two — walkdir and dashmap — do not have a clear successor and remain widely used.

The headline here is parity, not catastrophe. Rust shows the same 8% abandonment rate as npm among foundational packages. Rust's reputation for safety, its strong type system, its memory-management guarantees — none of that extends to maintenance-stage longevity. A package whose code never panics is still a package whose maintainer can burn out.

This is the same structural-decline pattern documented in the Stack Overflow question decline audit — a public, auditable signal of channel health that erodes independently of underlying technology popularity.

Story E — PyPI's at-risk concentration in the Pallets ecosystem

PackageStarsDays silentOwner
jinja211,620327pallets/
markupsafe688223pallets/
pyyaml2,888224yaml/

Jinja2 and MarkupSafe are both maintained by the Pallets project (Flask's parent organisation). Both are at 200-330 days silent — not yet "abandoned" by the audit's definition, but clearly slowing.

The Pallets concentration matters because it's organisationally explicable. A small group of maintainers (historically driven by Armin Ronacher) drove velocity across Flask, Jinja, MarkupSafe, Click, and ItsDangerous. When a small group of maintainers slows down, multiple foundational packages slow in lockstep. This is the structural pattern the broader OSS-maintainer-burnout discourse — including the Linux Foundation's 2024 maintainer report — has been describing for a decade.

The named-cohort detail matters. Three Pallets-adjacent packages slowing together is a different signal from three random PyPI packages slowing. The first looks like a maintainer-cohort capacity issue; the second looks like statistical noise. The actor-side enrichRepoData: true flag captures the owner organisation, which is what allows that pattern to surface.

Methodology

  • Phase 1 — Registry resolution: The new bash scripts/ms research oss-burnout-index command in the ApifyForge ms-CLI queries the public package-registry APIs for npm (registry.npmjs.org), PyPI (pypi.org), and crates.io (crates.io). For each package, the script extracts the canonical GitHub repository URL from the package metadata: repository.url for npm, info.project_urls.Source for PyPI, crate.repository for cargo. Phase 1 is free and uses public APIs.
  • Phase 2 — GitHub enrichment: The resolved owner/repo list is passed to ApifyForge's github-repo-search Apify actor in batches of 20 (the actor's compareRepos cap), with mode: "dependency-audit" + enrichRepoData: true + a GitHub PAT for elevated rate limits. The actor returns per-repo pushedAt, daysSinceLastPush, isAbandoned, isArchived, plus enrichment fields (community profile health, latest release, owner organisation).
  • Sample size: 50 packages each on npm and crates.io (top-50 most-depended-on by 2026-05-08 popularity rankings). 36 of 50 PyPI packages had a repository.url exposed in registry metadata; 14 PyPI packages had Homepage: pypi.org only and were excluded from the audit. Total: 136 packages with successful end-to-end resolution.
  • Categorisation: active (≤90 days since last push), low activity (91-180 days), stale (181-365 days), abandoned (>365 days), archived (boolean from GitHub). Categories are non-overlapping except archived (which can co-occur).
  • Reproduction: all numbers are reproducible from public sources. The ms research oss-burnout-index command + the github-repo-search actor with the same input list will produce comparable numbers any day. Source data archived at storage/research/oss-burnout-index/audit.json in the ApifyForge repo.
  • Cost: 8 actor runs × ~$0.013 each = ~$0.10 in actor PPE charges. Free for the registry-resolution phase.
  • Two-phase architecture: the split between free registry-resolution (Phase 1) and paid GitHub enrichment (Phase 2) is deliberate. The actor specialises in GitHub activity intelligence; package-registry resolution is outside its scope and free via public APIs. Anyone with an Apify account and a public GitHub PAT can reproduce the audit end-to-end.

What the data does NOT support

Several inferences a journalist might want to draw from this dataset are not supported by it. Honest framing requires acknowledging them upfront.

1. "Abandoned packages are broken or unsafe to use." The audit measures activity, not quality. A package with no commits in 365 days may be feature-complete, stable, and entirely safe. moment.js is the clearest example — its silence is a deliberate maintenance-mode posture by maintainers who explicitly state the library is done. "Abandoned" in this dataset is a behavioural label, not a security verdict.

2. "Maintainer burnout caused these abandonments." The data is a single 8 May 2026 snapshot. It captures the activity state at one moment. Maintainer burnout is real and well-documented elsewhere (Linux Foundation 2024 report, Tidelift surveys, Open Source Security Foundation research), but this specific dataset cannot distinguish "burnout" from "deliberate completion" from "natural successor exists" from "maintainer changed jobs and the repo never got reassigned." Multi-causality is the correct framing.

3. "These packages have N million downstream dependents." Stars are a footprint proxy; they understate the impact of low-star, high-dependent-count packages (MarkupSafe at 688 stars is pulled in by Flask, Jinja, and millions of derived projects). True dependent-count data requires libraries.io or registry-level dependent-tracking that this audit doesn't query.

4. "PyPI is the healthiest ecosystem." The 0% abandonment rate on PyPI in this audit is partly an artefact of the 14 packages excluded for missing project_urls.Source metadata. PyPI's at-risk concentration in the 180-365 day window also suggests that PyPI's at-risk packages may be earlier in their staleness curve, not absent. A 2027 follow-up would clarify whether they cross the 365-day line or recover.

5. "Bus factor risk is high for these packages." The actor's contributors.count field returned 1 for almost every repo in the run. That is an actor-side enrichment limitation, not a true 1-contributor signal. Coverage should not infer bus-factor risk from this dataset; the activity signal stands alone. Bus-factor measurement requires a direct GitHub /repos/{owner}/{repo}/contributors?per_page=100 call, which is on the follow-up roadmap. The general framework for bus factor analysis on GitHub projects is documented separately.

6. "The Rust ecosystem is in trouble." The 8% abandonment rate matches npm. It is not anomalously high for an ecosystem that's a decade younger than npm. The story is parity with the most-depended-on JavaScript ecosystem, not Rust-specific decline.

7. "GitHub is the canonical home for all these packages." A small fraction of registry packages declare GitHub URLs that are mirrors rather than primary repos (canonical work happens on GitLab, Codeberg, or self-hosted forges). This is rare but happens. A package whose GitHub is a sync-mirror may show artificial silence.

8. "The 14 PyPI packages excluded would change the headline." The 14 excluded (urllib3, numpy, pandas, scipy, scikit-learn, tensorflow, sqlalchemy, beautifulsoup4, cryptography, celery, gunicorn, charset-normalizer, openpyxl, tqdm) are mainstream, actively-maintained projects. Including them would round out the PyPI sample but not move the abandonment rate above zero. The gap is in audit completeness, not in headline conclusion.

9. "GitHub's pushed_at measures all maintainer activity." It reflects pushes to the repo's default branch. A repo with active development on feature branches but no merges to default for 90+ days will register as low-activity. This is rare for foundational packages (which typically merge to main/master frequently) but worth disclosing.

Common misconceptions

  • "Abandoned means broken." No. moment.js is abandoned by this audit's behavioural definition, but it works, it's stable, and its maintainers explicitly chose maintenance mode. Abandoned ≠ broken. Abandoned ≠ unsafe. Abandoned = "no commits in 365+ days" — full stop.
  • "Archived packages are removed from registries." GitHub's archive flag makes the repo read-only. It does not remove the package from npm, PyPI, or crates.io. prop-types and bincode are both still installable and downloaded daily despite being archived.
  • "Migration is automatic when maintainers deprecate a package." It is not. The request deprecation in 2020 has not removed request from the npm dependency graph. Downstream packages high in the tree pin to it; consumers below them inherit it transitively. A maintainer's decision to stop is not a signal that propagates without active migration work.
  • "Star count tracks downstream usage." Stars are a proxy, and an imperfect one. MarkupSafe has 688 stars and is pulled in by every Flask install — millions of downstream consumers. Stars correlate with footprint loosely; they don't measure dependent count.
  • "Rust's safety story includes maintenance longevity." It does not. The audit shows identical abandonment rates between Rust and JavaScript among foundational packages. The language guarantees safety at compile time; nothing in the language guarantees the maintainer keeps showing up.

Glossary

  • Abandoned (this audit's definition) — a package with zero pushes to its default branch on GitHub for 365 or more days as of the capture date.
  • Stale (this audit's definition) — a package with zero pushes for 181-365 days.
  • Archived — a GitHub repository state where the maintainer has explicitly marked the project as read-only. New issues and PRs are blocked. The package may still be installable from its registry.
  • pushed_at — the GitHub API field representing the timestamp of the most recent push to the repository's default branch.
  • enrichRepoData: true — an input flag on the github-repo-search actor that enables additional GitHub-API calls per repo to fetch latest release, contributor count, owner organisation, and community profile health.
  • Foundational package — in this audit, a package that ranks in the top 50 most-depended-on for its registry. Operationally synonymous with "any minor language change ripples across millions of downstream codebases."

Press lift-out paragraph for journalists

For trade-press, newsletter, and analyst use:

A 2026 ApifyForge audit of 136 most-depended-on packages across npm,
PyPI, and crates.io found 8 (5.9%) have had zero maintainer activity
in over 365 days, and 12 (8.8%) have been silent for 180+ days. The
named abandoned packages include moment (47,978 stars, 632 days
silent), request (25,565 stars, 632 days, officially deprecated),
facebook/prop-types (4,454 stars, 721 days, archived), structopt
(2,727 stars, 851 days), and lazy_static (2,030 stars, 464 days). Two
are explicitly archived on GitHub (prop-types and bincode) yet remain
shipped as transitive dependencies in millions of production
codebases. The npm and crates.io ecosystems show identical 8%
abandonment rates among foundational packages; PyPI's at-risk
packages cluster in the 180-365 day stale window rather than the
>365-day abandoned window.

Mini case study — the prop-types archive event

Before: prop-types was a foundational React utility, carved out of React 15.5 in 2017 as a standalone npm package. It ran on millions of React installs as a peer dependency for runtime type validation in components, particularly in pre-TypeScript-era codebases.

Engagement state: As of the 8 May 2026 capture, the facebook/prop-types repository is archived (read-only, no PRs accepted, no issues filable) with 721 days since the last push. Star count: 4,454. The package remains installable from npm and is still downloaded at scale because legacy React codebases haven't migrated to TypeScript.

Comparison: The closest comparator in this audit is bincode-org/bincode (266 days silent, 3,074 stars, also archived). Both packages have followed the same trajectory: the maintainers explicitly ended the project, the GitHub repo went read-only, the registry listing stayed live, and downstream consumers continued to ship the package as a transitive dependency.

State as of capture (May 2026): prop-types is the cleanest illustration in the audit of the gap between maintainer intent and downstream behaviour. The maintainer signalled "do not use this" by archiving. Most downstream consumers haven't acted on the signal because migration takes work and the existing install path keeps working.

These numbers reflect one capture of public GitHub metadata on 8 May 2026 via one specific actor configuration. Anyone with an Apify account and the github-repo-search actor can re-run the same query and verify the figures. Reproducibility is the point.

What are the alternatives to this kind of audit?

Several methods exist for measuring OSS package health at the dependency-graph scale. Each has tradeoffs.

ApproachWhat it measuresWhere it breaks at scale
github-repo-search actor in dependency-audit mode (used here)Per-repo days-since-push, archive status, star count, latest release, owner orgBound by GitHub API rate limits; sample is editorial choice of input list
Libraries.io APICross-registry per-package metadata, dependent counts, version historyFree tier rate-limited; coverage gaps in some ecosystems
OpenSSF ScorecardSecurity and maintenance score per repo (binary attestation, branch protection, etc.)Security-focused, not activity-focused; per-repo computation overhead
GitHub API direct (/repos/{owner}/{repo})Single-repo activity statsRate-limited at 5,000 req/hr authenticated; you build the cohort logic yourself
Snyk Open Source / Sonatype IQVulnerability and maintenance signals, commercial CVE feedsSubscription-priced; vendor-specific scoring methodology
npm outdated / cargo outdated / pip list --outdatedPer-project staleness against latest published versionPer-project, not cross-cohort; doesn't capture maintainer activity
Manual journalist samplingCurated subjective read of a few flagship packagesAnecdotal; not reproducible; misses long-tail patterns

Pricing and features based on publicly available information as of May 2026 and may change.

Each approach has tradeoffs in granularity, reproducibility, ecosystem coverage, and cost. For a named-package, days-silent, archived-aware, multi-ecosystem audit with reproducible numbers, the github-repo-search actor in dependency-audit mode is the most direct mechanism. For richer follow-up — true downstream-dependent counts via libraries.io, weekly download volume from registry stats, or year-over-year drift via repeated captures — combining the actor's output with additional public-API queries extends the audit further. The methodology pattern matches the tech podcast cemetery audit and the Stack Overflow question decline audit, which together with this post form the third entry in a methodology series documenting industry-channel decline through reproducible public-data captures.

Best practices for journalists citing this dataset

  1. Always pair the 5.9% headline with the 136-package scope. Frame as "8 of 136 audited packages" not "5.9% of all OSS."
  2. Use a specific named package with its days-silent figure as the quote anchor. "moment.js, 47,978 stars, 632 days silent" is more citable than the aggregate.
  3. Distinguish abandoned from broken. moment.js works. The 632-day silence is a deliberate maintenance-mode posture. The data does not say the library is unsafe; it says it isn't being touched.
  4. Date the snapshot. All figures are 8 May 2026 captures via the github-repo-search actor with the dependency-audit mode and enrichRepoData: true.
  5. Link to the methodology section for reproducibility — every figure can be re-fetched by re-running the actor with the same inputs.
  6. Disclose the 14-PyPI exclusion. PyPI's 0% abandonment rate is partly an artefact of the registry-metadata gap; the audit excluded 14 mainstream packages whose project_urls.Source field was missing.
  7. Separate "archived" from "abandoned." Archived is a maintainer's explicit decision; abandoned is a behavioural signal. prop-types and bincode are both. moment.js is only the latter.
  8. Quote the press lift-out paragraph verbatim if the framing needs to be standardised across outlets.

Common mistakes when citing this dataset

  • Treating "abandoned" as a quality verdict. It is a behavioural label. Some abandoned packages are stable and feature-complete; others are genuinely neglected. The data does not distinguish.
  • Inferring downstream impact from star count alone. Stars are a footprint proxy. MarkupSafe at 688 stars has more downstream consumers than packages with ten times the stars. Use stars as a comparative signal within the cohort, not as a true dependent count.
  • Generalising to "all of OSS." This audit covers 136 packages. The full npm registry has over 4 million packages; PyPI has over 600,000; crates.io has over 180,000. The headline applies to the foundational top-of-cohort, not to OSS broadly.
  • Treating the npm/cargo parity as cargo-ecosystem failure. It is a Rust-vs-marketing reality check. The 8% abandonment rate is comparable to npm's, not anomalously high.
  • Conflating "no recent push" with "no recent maintenance." A repo with active feature-branch development that hasn't merged to default for 365 days will register as abandoned. This is rare for foundational packages but worth disclosing.
  • Ignoring the archive distinction. prop-types has been archived for 721 days. bincode for 266. The maintainers have explicitly ended these projects. That is a different signal from "no commits" — it is "no commits AND maintainer has formally walked away."

Implementation checklist for re-running the audit

  1. Sign up for an Apify account at apify.com.
  2. Generate a GitHub personal access token with public_repo scope (the actor uses it for elevated rate limits).
  3. Pull the top-N most-depended-on packages list for each registry you care about — npm, PyPI, crates.io. The bash scripts/ms research oss-burnout-index command does this from public registry APIs in Phase 1.
  4. Resolve each package's GitHub repo URL from registry metadata (repository.url for npm, info.project_urls.Source for PyPI, crate.repository for cargo).
  5. Batch the resolved owner/repo pairs into groups of 20 (the actor's compareRepos cap).
  6. Run the github-repo-search actor with mode: "dependency-audit", enrichRepoData: true, your GitHub PAT, and one batch of 20 repos per run.
  7. Aggregate the per-repo pushedAt, daysSinceLastPush, isAbandoned, and isArchived fields from each dataset.
  8. Categorise packages by activity tier (active <90d, low 91-180d, stale 181-365d, abandoned >365d).
  9. Publish the spreadsheet alongside the analysis. Reproducibility is the entire point.

Limitations

  • The audit is a single 8 May 2026 snapshot. Maintainer activity is a live signal. A "stale" package today may receive a flurry of commits next week. An "active" package today may go silent next month. The dataset is point-in-time.
  • The 50-package-per-ecosystem seed is editorial. A different selection would shift the at-risk count slightly but not the structural finding. The packages chosen are mainstream foundational dependencies; no editor would dispute their importance, but expanding to 200 per ecosystem would tighten the percentages.
  • 14 PyPI packages were excluded because their project_urls.Source metadata was missing or non-GitHub. These are major libraries (urllib3, numpy, pandas, scipy, scikit-learn, tensorflow, etc.). Their omission affects PyPI's at-risk percentage but not the overall ecosystem comparison.
  • Bus-factor data is not in this audit. The actor's contributors.count field returned 1 for almost every repo, which is an actor-side enrichment limitation rather than a true 1-contributor signal. Coverage should not infer bus-factor risk from this dataset.
  • Downstream-impact is approximated by GitHub stars. True dependent-count data requires libraries.io or registry-level dependent-tracking that this audit doesn't query.
  • GitHub may not be the canonical home for some packages. A small fraction of registry packages declare GitHub URLs that are mirrors rather than primary repos. This is rare but happens.
  • No year-over-year comparison. A 2025 baseline would allow YoY drift analysis but does not currently exist. Repeated captures every 6 months would document whether the abandoned cohort grows over time.

Key facts about the OSS Maintainer Burnout Index

  • 136 most-depended-on packages across npm, PyPI, and crates.io were audited 8 May 2026.
  • 8 packages (5.9%) have zero maintainer activity in 365+ days — the audit's "abandoned" threshold.
  • 12 packages (8.8%) are silent for 180+ days when the stale tier is included.
  • 2 packages are explicitly archived on GitHub: facebook/prop-types and bincode-org/bincode.
  • moment.js leads the abandoned cohort by stars: 47,978 stars and 632 days silent.
  • npm and crates.io show identical 8% abandonment rates among foundational packages.
  • PyPI's at-risk slice clusters in the 180-365 day window — Jinja2 (327 days), PyYAML (224), MarkupSafe (223).
  • The audit is reproducible via ApifyForge's github-repo-search Apify actor at roughly $0.10 in PPE charges per full run.

Broader applicability

These patterns apply beyond OSS package registries to any system where named entities erode through measurable behavioural signals while remaining listed and consumed:

  • Behavioural signals beat reputation signals for current state. Days-since-last-push tells you more about a package's current maintenance state than star count or download volume. The same is true of any "is this thing still alive" question — last activity date dominates lifetime metrics for current-state inference.
  • Channel decline is independent of underlying activity. A package can be technologically essential and structurally abandoned simultaneously. The same way Stack Overflow's question intake collapsed channel-by-channel without the underlying programming languages declining, OSS packages can become foundational and unmaintained at the same time.
  • Maintainer-cohort dynamics produce lockstep slowdowns. When a small group of maintainers covers multiple packages (Pallets / Jinja / MarkupSafe), all of them slow together. This is the structural pattern any ecosystem with concentrated maintainership exhibits.
  • Archive flags are organisational decisions, not migration events. GitHub archive marks the maintainer's exit. Downstream migration is a separate, slower, often-incomplete process.
  • Reproducibility is the press currency. Audit datasets that anyone can re-run from public APIs via a public actor are easier for journalists, researchers, and security teams to cite than proprietary internal numbers.

When you need this analysis

You probably want to reference this dataset if:

  • You're writing about software supply-chain risk, OSS sustainability, or maintainer burnout.
  • You're reporting on a specific named package's health (moment.js, request, prop-types, lazy_static, etc.).
  • You need a named-package, days-silent quantitative anchor for an "OSS is in trouble" feature.
  • You're briefing security, platform-engineering, or developer-relations leadership on dependency-graph silent-tail risk.
  • You want a reproducible, named-package, dated dataset rather than vibes.
  • You're sourcing methodology for a follow-on analysis (longitudinal, cross-ecosystem, or per-package deep-dive).

You probably don't need this if:

  • You want true downstream-dependent counts — that requires libraries.io or registry-level data this audit doesn't query.
  • You want vulnerability or CVE data — Snyk, OSSF Scorecard, or Sonatype are the right surfaces.
  • You want bus-factor measurement — the actor's contributors.count field is unreliable in this run; a direct GitHub /contributors API call is needed.
  • You want year-over-year drift — this is a single 8 May 2026 snapshot.
  • You want a moral verdict on OSS maintainer treatment — this dataset is behavioural, not ethical.

How to verify any single package in this dataset

Each package's days-silent and archive status is re-fetchable from the public GitHub API. To verify any individual figure:

  1. Visit the repository directly (e.g., moment/moment, request/request, facebook/prop-types).
  2. Read the "last commit" timestamp on the default branch and check for the archive banner at the top of the page.
  3. Compare to the leaderboard table in this post.
  4. To reproduce at scale, use the github-repo-search Apify actor with mode: "dependency-audit", enrichRepoData: true, and the same input list documented in the methodology section.

Frequently asked questions

How does the audit define "abandoned"?

Abandoned in this audit means zero pushes to the GitHub repository's default branch in 365 or more days as of the 8 May 2026 capture date. It is a behavioural threshold, not a quality assessment. The label is descriptive of activity state, not prescriptive of whether the package should be used. Some abandoned packages — moment.js is the clearest example — are stable, feature-complete, and in deliberate maintenance mode by their maintainers' explicit decision.

Is moment.js safe to use even though it's abandoned?

The moment.js maintainers publish a project status statement explaining that the library is in maintenance mode and recommending day.js, luxon, or date-fns as alternatives for new projects. Existing moment.js code continues to work. Whether to migrate is a per-project tradeoff between migration cost and the value of moving to an actively-developed library. The audit does not flag moment.js as unsafe; it flags it as silent.

Why does Rust have the same abandonment rate as JavaScript?

The 8% parity reflects the reality that maintainership is a human capacity problem, not a language-design problem. Rust's safety guarantees apply at compile time. Nothing in the language prevents a maintainer from burning out, changing jobs, or simply deciding the project is done. The most-depended-on cargo crates show the same long-tail-of-silence pattern as the most-depended-on npm modules. The age difference between the ecosystems (npm 2010, cargo 2014) and the 8% parity is the headline.

What does archived mean and why are archived packages still installed?

Archived on GitHub means the maintainer has set the repository to read-only — no new issues, no merged pull requests, no pushes. It is the strongest "do not use this" signal short of unpublishing from the registry. But archiving on GitHub does not unpublish from npm, PyPI, or crates.io. The package remains installable. Downstream consumers don't migrate automatically — they have to actively choose to migrate, which most don't, especially for transitive dependencies they're unaware of.

Is the Pallets ecosystem in trouble?

The audit captures Jinja2 at 327 days silent, MarkupSafe at 223, and Flask's other Pallets-org packages on a similar slope. None has crossed the 365-day abandoned threshold yet. The signal is "slowing in lockstep," consistent with small-maintainer-cohort capacity dynamics that the broader OSS-burnout literature has documented. A 2027 follow-up would clarify whether the slowdown continues or reverses.

Can I reproduce this audit myself?

Yes. The methodology section documents the full two-phase pipeline. Phase 1 (registry resolution) uses public APIs and is free. Phase 2 uses the github-repo-search Apify actor at roughly $0.013 per run; the full 136-package audit costs about $0.10 in actor PPE charges. You'll need an Apify account and a GitHub personal access token with public_repo scope for the elevated GitHub rate limits. The full input list is in the dataset doc at docs/BACKLINK-BAIT-026-OSS-BURNOUT-INDEX-DATASET.md in the ApifyForge repo.

How does this compare to OpenSSF Scorecard or Snyk?

Different scope and different focus. OpenSSF Scorecard measures security-and-maintenance attestation per repo (binary attestation, branch protection, SAST configuration). Snyk produces commercial vulnerability and maintenance feeds priced by subscription. This audit is narrower: it measures days-since-last-push and archive status across a 136-package foundational cohort, in one snapshot, using public APIs, reproducible by anyone with an Apify account. It is complementary to security-focused tools rather than competitive with them.

A note on the underlying tools

This post is the eleventh in an ApifyForge backlink-bait series documenting structural patterns through reproducible public-data audits. It is the third in the series specifically built around named-entity ranking through industry-channel decline through public APIs, alongside the tech podcast cemetery audit (68 dormant tech podcasts, 8,123 abandoned episodes) and the Stack Overflow question decline audit (40 tags, 94.9% question-volume collapse). All three follow the same methodology pattern: pick a public dataset, capture it as of a specific date via a reproducible Apify actor, publish the per-row figures alongside the methodology, and let the named-entity rankings do the journalism.

Other posts in the ApifyForge backlink-bait series:

The dataset for this post was generated using the github-repo-search Apify actor in dependency-audit mode — the same tool security teams, platform engineers, and analysts can use for ongoing dependency-graph health audits across npm, PyPI, and crates.io.

Ryan Clinton publishes Apify actors and MCP servers as ryanclinton and runs ApifyForge.


Last updated: May 2026

This guide focuses on npm, PyPI, and crates.io foundational packages, but the same activity-snapshot patterns apply broadly across any public software registry where maintainer engagement is observable through repository-level signals.