Pick any Node repo you own and run this. Takes about ten seconds.
// bus-factor.mjs — rank your deps by how few people can publish them
import { readFileSync } from 'node:fs'
const pkg = JSON.parse(readFileSync('package.json', 'utf8'))
const deps = Object.keys({ ...pkg.dependencies, ...pkg.devDependencies })
const rows = await Promise.all(deps.map(async (name) => {
const meta = await fetch(`https://registry.npmjs.org/${name}`)
.then(r => r.ok ? r.json() : { maintainers: [] })
const dl = await fetch(`https://api.npmjs.org/downloads/point/last-week/${name}`)
.then(r => r.json()).catch(() => ({ downloads: 0 }))
return { name, owners: (meta.maintainers ?? []).length, weekly: dl.downloads ?? 0 }
}))
rows
.filter(r => r.owners === 1)
.sort((a, b) => b.weekly - a.weekly)
.forEach(r => console.log(`${String(r.weekly).padStart(12)} ${r.name}`))
Everything it prints is a package where exactly one npm account can publish a new version. Not one contributor. One person holding the keys. On a mid-sized app I ran this against, 61 of 340 direct and dev dependencies came back with a single owner, and the top of the sorted list was moving nine figures of downloads a week.
That's the number worth sitting with before anyone talks about supply chain strategy.
The script is optimistic
The registry's maintainers field means publish rights, not activity. Someone who hasn't opened the repo since 2021 still counts as an owner. So a package showing three maintainers can easily be one active human and two people who moved on. The real distribution is worse than what you just printed.
PyPI's JSON API is even less helpful here, so for Python use OpenSSF Scorecard, which looks at commit activity rather than account lists:
scorecard --repo=github.com/psf/requests --checks=Maintained,Contributors
Maintained scores recent commit and issue activity over the last 90 days. A 0 there on something in your production path is a finding, not a curiosity.
Three incidents that were funding problems wearing a code costume
Heartbleed, 2014. OpenSSL was securing a large share of the web's TLS on donations of roughly two thousand dollars a year. Not two thousand per contributor. Two thousand, total. The bug was a missing bounds check, and the missing bounds check was downstream of nobody having time to review.
Log4Shell, December 2021. CVSS 10.0, and the patch cycle ran through a holiday weekend, handled by a small group of volunteers while every Fortune 500 SOC on earth was paging. The companies that depended on Log4j had eight-figure security budgets. The library had a Slack channel.
xz Utils, February 2024. This one is the sharpest, because the attack surface was the maintainer. Sustained social pressure on a burned-out solo maintainer until a helpful new co-maintainer with commit rights looked like relief instead of a threat. The backdoor reached sshd through liblzma and got caught because a Postgres developer noticed his SSH logins had gotten about half a second slower and refused to let it go.
None of those were caused by bad engineering. They were caused by the ratio between how much the software was worth and how many people were paid to keep it alive.
Why nobody writes the check
The Linux Foundation and Harvard's Census II found that 136 developers were responsible for more than 80% of the lines of code in the top 50 npm packages. Tidelift's maintainer surveys have consistently found that roughly half of maintainers earn nothing at all from the work, and only a thin slice clear a thousand dollars a year.
The blocker usually isn't willingness. It's that procurement can process a forty-thousand-dollar observability contract in two weeks and cannot process two hundred dollars a month to an individual in Finland. There's no vendor record, no MSA, no security questionnaire to fill out, no PO number. The system is built to buy from companies, and the dependency is a person.
There's a measurement asymmetry too. You can put a dollar figure on the outage. You can never put one on the maintenance that stopped the outage from happening, so it always loses the budget argument.
What actually moves, ordered by effort
Start with npm fund. It's already in your toolchain, it reads your lockfile, and it prints funding URLs for everything in your tree. Two minutes, no new tooling.
Then make the giving proportional. thanks.dev and Open Source Collective both split a monthly amount across your actual dependency graph rather than whatever's trending. Five hundred a month distributed by real usage does more than five thousand to one popular project.
Vendor the small stuff. If a dependency is forty lines with one owner, copy it in with the license header and attribution intact. You've removed a publish-rights risk and stopped pretending someone else is on call for it.
Harden the install path. Committed lockfile, npm ci, --ignore-scripts where your build tolerates it, and Dependabot PRs that a human actually reads. The xz backdoor shipped in a release tarball that didn't match the git tree, so build from source where it's cheap enough to do.
The view from the other side
I maintain one of these. Small Python library, single owner, and it exists because of a bill.
An agent loop of mine had a retry-on-parse-error path where the counter never incremented. The model kept producing output that failed a schema check, the wrapper kept retrying, and it ran unattended overnight. Roughly 1.1 million output tokens and about $340 before I saw it at breakfast. My provider budget alert fired. Four hours after the loop started.
That's the design lesson, and it's why the enforcement has to happen before the request leaves your process:
| Control | Fires when | What it doesn't stop |
|---|---|---|
| Provider budget alert | after spend is recorded, often minutes late | the spend that triggered it |
| Rate limit (RPM/TPM) | at the request boundary | a slow loop that stays under the limit for six hours |
| Pre-flight cap | before the socket opens | usage inside one already-approved call |
So baar-core is a pre-flight kill switch. It checks the cap, and if you're over it, the provider is never contacted at all:
from baar_core import Budget, BudgetExceeded
budget = Budget(limit_usd=5.00, key=f"user:{user_id}:day")
try:
with budget.reserve(estimated_usd=0.04):
resp = client.messages.create(...) # only runs if the reservation held
except BudgetExceeded as e:
return Response(status=402, body=f"over cap: {e.spent} of {e.limit}")
The reserve() context manager matters more than the cap itself. Twenty parallel agents that each read "spent so far" and each independently conclude they're under budget will jointly blow straight through it. Reservation makes the read and the commit one atomic operation, so the twentieth agent gets a 402 instead of a share of the overrun. pip install baar-core if you want it.
It's free because charging for it would mean invoicing teams at the exact moment they discovered they'd been billed for a bug, and that's a worse world to build. noburn.dev is what we built on top of it for teams that need more than a library: same pre-flight enforcement, blocking calls before they fire when a user goes over budget, plus per-user caps and a spend history you can hand to finance.
Which also means I'm currently a single-maintainer row in somebody else's script output. I know exactly what that costs, and I still can't tell you how to price it.
What's the highest-download single-maintainer package in your tree, and would your team notice if that person stopped answering email?
Originally published at https://robatdasorvi.com/stories/why-open-source-won-and-what-that-victory-cost
Top comments (0)