Skip to content
Methodology · v3.2 · revised 2026-01-14

The Production Readiness Index — how the 0–100 score is actually calculated.

Every package in OpenLib's 1,247,392-package catalog is scored on the same four production signals. This document explains what those signals are, how they are normalized, and how they are combined — so engineering managers, security leads, and procurement teams can cite a defensible number in vendor reviews.

  • Download velocity
  • Issue half-life
  • Bus-factor
  • CVE history
Pillar overview

Every package is scored across exactly four production signals.

No paid placements, no editor picks, no SEO boosts. The composite score is a deterministic function of four public, measurable signals — each one sampled from data engineering managers already check during a dependency review.

01

Download velocity

Trailing-90-day install volume across npm, PyPI, Maven, crates.io, Go modules, and RubyGems. Log-scaled and normalized per ecosystem so a niche crate can compete fairly with a mainstream framework.

Weight · 25%
02

Issue half-life

Median time between a GitHub issue being opened and closed (or triaged with a maintainer response). Penalizes projects with rotting backlogs and rewards those that close the loop quickly.

Weight · 25%
03

Bus-factor

Distribution of commits, reviews, and release rights across active contributors. A project driven by a single maintainer with no co-maintainer scores lower than one with healthy succession depth.

Weight · 25%
04

CVE history

Severity-weighted count of published CVEs against the package and its direct dependencies over the trailing 24 months, discounted by how quickly each was patched after disclosure.

Weight · 25%
The formula

How the four pillars become a single 0–100 number.

Each pillar is rescaled to a 0–100 range using a piecewise-linear normalization that is calibrated per ecosystem. The composite score is the equal-weighted mean of those four pillars, then clipped and rounded to one decimal.

Composite score PRI = clip( ( DV + IH + BF + CV ) / 4, 0, 100 )
  • DV · Download velocity (0–100)
  • IH · Issue half-life (0–100)
  • BF · Bus-factor (0–100)
  • CV · CVE history (0–100)
01 · Download velocity

How we count an "install" without double-counting CI bots.

Raw install counts include CI farms, mirror traffic, and dependency-confusion noise. OpenLib deduplicates installs by SHA-256 of (registry client IP, package version, user-agent class) over a 24-hour window, then log-scales the remaining count against the per-ecosystem 95th percentile recorded in the trailing 12 months. A package at the 95th percentile scores 100; the median scores 62; the 5th percentile scores 18.

DV = round( 100 · log10(1 + installs_dedup) / log10(1 + p95_installs) )
02 · Issue half-life

Closing the loop — measured from the first maintainer reply, not from issue creation.

We sample the median time-to-first-maintainer-response across the trailing 200 issues (or all issues if the project has fewer). Projects under 12 hours score 100; projects at 14 days score 50; projects over 90 days score 5. Issues tagged question, discussion, or duplicate are excluded to avoid penalizing helpful maintainers for being conversational.

IH = piecewise_linear( median_first_response_hours, [(12,100),(336,50),(2160,5)] )
03 · Bus-factor

Concentration of authorship, weighted by recent activity.

We compute a Herfindahl–Hirschman Index over commit authorship in the trailing 12 months, then subtract a co-maintainer credit for every contributor with release-publish rights on the upstream registry. The score is 100 when the top contributor holds less than 25% of recent commits AND at least three co-maintainers hold publish rights. A solo-maintainer project with no co-maintainer scores 10.

BF = clamp( 100 - 2.5·HHI_top + 5·co_maintainers, 0, 100 )
04 · CVE history

Severity-weighted, time-discounted, with a fast-patch bonus.

Each CVE published against the package or its direct dependencies in the trailing 24 months contributes a penalty of CVSS × 4 points, discounted linearly so a 2-year-old CVE carries 12.5% weight. A patch released within 7 days of disclosure recovers 70% of that penalty. A package with zero CVEs and a clean SBOM scores 100. A package with a fresh unpatched RCE scores below 20.

CV = clamp( 100 - Σ penalty_i · discount_i · (1 - 0.7·fast_patch_i), 0, 100 )
Coverage & freshness

The dataset behind the score.

Numbers an engineering manager should see before citing any Index score internally.

1,247,392 indexed packages across npm, PyPI, Maven, crates.io, Go modules, RubyGems
180ms average query latency across the full index, measured weekly from 6 regions
15min refresh cadence CVE and download signals re-indexed every 15 minutes
9.4M/day public API requests 99.97% uptime over the trailing 12 months
Reproducibility

Every score is independently reproducible from public data.

Yes — and that is the point.

The full catalog is available as a Parquet export under CC-BY-SA 4.0, refreshed nightly. Methodology weights are versioned: every Index score in the database carries a methodology_version field, so a score produced under v3.0 can be recomputed today by pinning the formula version. The public REST API exposes a ?explain=1 flag that returns the four pillar sub-scores and the normalization buckets used, for any package, with no authentication required.

Researchers at eleven universities have used the export to replicate OpenLib's rankings against ground-truth dependency graphs scraped from production monorepos. The published error margin against these independent replications is under 0.4 points on the 0–100 scale. If your team finds a discrepancy larger than that, open an issue on openlib/methodology and we will publish a post-mortem within ten working days.

  • Parquet export · full catalog under CC-BY-SA 4.0 · refreshed nightly · checksum-signed
  • Versioned weights · every score carries its methodology_version; v3.0 scores remain reproducible today
  • ?explain=1 · any API query returns the four pillar sub-scores and normalization buckets on demand
  • Open correction log · every methodology change since 2019 is git-versioned at github.com/openlib/methodology
FAQ

The questions engineering managers ask before citing an Index score.

If yours is not here, write to [email protected] — we publish new answers monthly.

Can a package buy a higher score?

No. The score is a deterministic function of four public signals — downloads, issue response time, contributor concentration, and CVE history. None of these are sellable, sponsorable, or boostable through any paid tier. The Pro tier ($19/mo) mirrors private packages into a team's index; it does not alter the public score of any package.

How do you handle a package with no CVE history because nobody looks at it?

A package with zero published CVEs is not assumed to be safe — it is assumed to be unobserved. The CVE pillar scores 100 only when the SBOM is clean AND the package has been in the index for at least 12 months AND its direct dependencies have been scanned by at least one of the major advisory databases (NVD, GHSA, OSV). New packages are held at a neutral 60 until they accumulate enough observation history to be scored fairly.

Why is the bus-factor pillar not weighted higher?

Bus-factor is an excellent long-term risk signal but a noisy short-term one. A solo maintainer who has shipped every release for six years is, today, a very low operational risk — and penalizing them heavily for being solo would distort rankings against small-but-excellent libraries. We expose bus-factor as a separate filterable attribute so security and succession planning teams can weight it differently in their own private indexes without affecting the public composite.

Can we cite this methodology in our vendor review documentation?

Yes — citation is explicitly encouraged. The recommended citation format is in the methodology repository at github.com/openlib/methodology, and includes the methodology version, the retrieval date, and the SHA-256 of the Parquet snapshot you queried against. A PDF version of this page is available for inclusion in procurement packets; request it via the contact email above.