The Regex Packages You Depend On Have One Maintainer Between Them
Download counts tell you how many people pull a package. They cannot tell you whether anyone is still home. This page measures the second thing.
Every cell below is the registry's own value for the package's latest dist-tag, read on 2026-10-13 from registry.npmjs.org/<pkg>. Ages are stated against that same fixed date and never as "X days ago", because a relative cell is true the day it is written and wrong every day after. Re-check any row with node scripts/pull-registry-meta.mjs <pkg>; verify-registry-meta.mjs re-runs the whole table in CI.
The eight packages, as the registry has them
| Package | Latest | Released | Maintainers | Deps |
|---|---|---|---|---|
escape-string-regexp | 5.0.0 | 2021-04-17 | 1 | 0 |
safe-regex | 2.1.1 | 2019-10-21 | 1 | 1 |
escape-regexp | 0.0.1 | 2012-10-19 | 1 | 0 |
regexp-tree | 0.1.27 | 2023-04-30 | 1 | 0 |
re2js | 2.8.6 | 2026-07-05 | 1 | 0 |
xregexp | 5.1.3 | 2026-09-24 | 2 | 1 |
regexp-util | 2.1.0 | 2026-09-16 | 2 | 0 |
safe-regex2 | 5.1.2 | 2026-10-10 | 2 | 1 |
Counts, from the table and nothing else:
- 5 of 8 have exactly one maintainer. One person, one npm password, one set of life circumstances. That is the bus factor of most of this ecosystem.
- 5 of 8 have zero runtime dependencies, which is the good news and the reason the old ones are still usable.
- 3 of 8 shipped within 30 days of 2026-10-13 (
safe-regex23 days,xregexp19,regexp-util27). All three are the two-maintainer ones. - The other five are between 100 days and 14 years since their last release.
Growth does not track upkeep
The same packages measured for downloads over the window 2024-10-01 to 2026-10-10 (first 30 days against last 30, pulled 2026-10-12 — full table on the libraries page):
| Package | First 30 days | Last 30 days | Change |
|---|---|---|---|
escape-string-regexp | 610.3M | 1.647B | +170% |
safe-regex2 | 8.024M | 87.64M | +10.9× |
safe-regex | 55.85M | 86.66M | +55% |
regexp-tree | 20.88M | 68.84M | +230% |
re2js | 0.30M | 34.54M | +115× |
xregexp | 13.45M | 15.85M | +18% |
regexp-util | 0.14M | 2.016M | +14.4× |
escape-regexp | 0.65M | 0.39M | −40% |
Set the two tables side by side and the correlation people assume — popular things get maintained — does not appear.
escape-string-regexp is the largest number in the set and the oldest single-maintainer package in it: 1.647B downloads in the last 30 days, growing +170%, last released 2021-04-17, which is 2,005 days (5.5 years) before the measurement date. It has zero dependencies, so nothing about it is complicated; it escapes . and * so an outside string cannot be read as a pattern. It is also, by the registry's account, five and a half years since anyone shipped a fix.
safe-regex is the one that should make you look twice. It detects catastrophic backtracking — the class of bug this site exists to help you avoid. It grew +55%, has one maintainer, and last shipped 2019-10-21: 2,549 days, seven years. A safety tool that has not been touched in seven years while its install count rises is not evidence it still works; it is evidence nobody has replaced it yet.
safe-regex2 is the market's answer to that sentence. Same job, two maintainers, 5.1.2 released 2026-10-10 — three days before this was pulled — and +10.9× growth. Two adjacent rows, one abandoned and one three days old, both growing. When a fork with a 2 on the end is out-growing the original, the maintenance gap is no longer theoretical.
escape-regexp is the honest ending of the story: 0.0.1, released 2012-10-19 (5,107 days), one maintainer, and downloads down 40%. Abandoned and shrinking, in the same table as its own replacement at 1.647B. Nothing about that pair is a surprise, which is the point.
What this does and does not prove
A release date is a fact. What it implies is not.
Old and single-maintainer is not the same as broken. escape-regexp at 14 years has had nothing to fix and nothing broken. Zero dependencies means the transitive supply-chain surface is genuinely empty — several of these are safer than a actively-maintained package with 40 dependencies. And npm's maintainer count measures publish access, not effort: it says how many people can ship a release, not how many review issues, so a package with one name and 300 open issues looks identical here to one with a team.
What the dates do prove is narrower and worth more: for the five single-maintainer packages here, a future fix is not something you can wait for. Not "unlikely" — the record says nobody has done it in 100 days to 14 years. So the decision is not "is this package good" but "can I live with being the person who forks it in 2028".
Do this
- Check the release date, not just the download count. The count tells you everyone else is there; the date tells you whether the exit is staffed.
- Prefer zero-runtime-dependency packages when they do the job. Five of these eight have none, and that is a real security property, not a stylistic one.
- Read a maintainer count of 1 as "one credential", and treat a fork out-growing the original as the strongest available signal that maintenance has moved.
- Pin exact versions for the stale ones. A floating range on a package nobody releases is a range that resolves the same forever — until someone else publishes on it.
- For ReDoS specifically, do not rely on a checker alone. Detecting the pattern is a heuristic; structuring the pattern so it cannot backtrack is the fix.
Related: regex libraries in 2026, regex gotchas, ReDoS protection, alternatives to the big engines.
Maintenance cells came from registry.npmjs.org on 2026-10-13 and are re-checked cell-by-cell by scripts/verify-registry-meta.mjs. Download cells are the published values from the libraries page, window 2024-10-01 to 2026-10-10, pulled 2026-10-12, verified by scripts/verify-npm-figures.mjs. Ages were computed against the fixed date 2026-10-13, not against "today". Prose readings of these numbers — "stale", "abandoned", "the market's answer" — are argument, not measurement, and the verifier deliberately leaves them alone.