How We Grade: ReleaseRun Methodology
ReleaseRun grades the health of technology versions on a scale from A to F. This page explains exactly how those grades are calculated, what data sources we use, and why some results might look surprising at first glance.
The Health Grade Formula
Every version gets a composite health score from 0 to 100, built from three equally-weighted sub-scores:
The score maps to a letter grade:
| Grade | Score Range | What It Means |
|---|---|---|
| A | 90+ | Current, secure, fully supported |
| B | 80-89 | Slightly behind or minor security notes |
| C | 65-79 | Getting stale, consider upgrading |
| D | 50-64 | Significantly outdated or has security issues |
| F | Below 50 | End of life, critical vulnerabilities, or both |
Sub-Score: Freshness (35%)
Freshness measures how many release cycles behind the latest your version is. We don’t penalize for age alone because LTS releases are designed to be used for years.
LTS: Score = 100 – (versions_behind × 6)
LTS versions get a gentler penalty because being a few versions behind on an LTS track is normal and expected. Node.js 22 LTS being 3 versions behind Node.js 25 is fine. Node.js 25 (non-LTS, short-lived) being 1 behind is a bigger relative concern.
Why Node.js 25 gets a C while Node.js 24 gets an A
This is the most common question we get. Node.js 25 is a Current (non-LTS) release with a short support window (about 6 months). Node.js 24 is an LTS release supported until April 2028. Even though 25 is “newer,” it has a worse freshness outlook because its support window is closing soon. The grade reflects health, not newness.
Sub-Score: Security (35%)
Security score starts at 100 and decreases based on known, unfixed CVEs:
We query OSV.dev using the latest patch version for each release cycle. This means we only count CVEs that are actually unfixed in the most recent patch. If you’re running Node.js 20.20.1 (the latest 20.x patch), you get credit for all the fixes in that patch.
Sub-Score: EOL Status (30%)
EOL scoring uses step bands based on time remaining until end of life:
- More than 1 year until EOL: 100 points
- 6-12 months until EOL: 80 points
- 3-6 months until EOL: 50 points
- 1-3 months until EOL: 20 points
- Less than 30 days until EOL: 5 points
- Past EOL: 0 points
Critical Overrides
Two conditions override the calculated grade regardless of score:
- Past EOL date: Grade forced to F immediately. End of life means no more security patches. There is no safe grace period.
- Any unfixed critical CVE: Grade capped at D (cannot be higher than D while critical vulnerabilities remain unpatched)
This is why Redis 8.0 (EOL February 2026) gets an F, not a D or C. Once a version stops receiving security patches, it fails. This is a deliberate design choice: we’d rather be honest about the risk than give false comfort.
Data Sources
We don’t make up version data. Everything comes from authoritative, well-maintained sources:
| Data | Source | Coverage |
|---|---|---|
| Release cycles, EOL dates, LTS status | endoflife.date | 300+ products |
| CVE data (unfixed vulnerabilities) | OSV.dev (Bitnami advisories) | Major runtimes, databases, frameworks |
| Cloud provider K8s support | EKS, GKE, AKS documentation | Kubernetes versions |
All data is fetched in real-time via API calls. Badge responses are cached for up to 1 hour to keep things fast, but the underlying data is always current.
Unknown Versions
If you request a badge for a version that doesn’t exist in our data sources (e.g., nodejs/99), we return “unknown version” rather than guessing. We’d rather say “we don’t know” than give you a misleading grade.
CLI Version Detection
The ReleaseRun CLI scans your project files to detect technology versions. How it handles different file types:
| Source | Type | How We Grade |
|---|---|---|
| .nvmrc | Pinned version | Exact version graded as-is |
| Dockerfile FROM | Pinned version | Exact version graded as-is |
| go.mod | Pinned version | Exact version graded as-is |
| engines.node >=18 | Minimum constraint | Resolved to highest active LTS version that satisfies the constraint |
| requires-python >=3.10 | Minimum constraint | Resolved to highest active version that satisfies the constraint |
| engines.node 18 || 20 || 22 | Version range | Highest version in the range is graded |
Limitations
We believe in being upfront about what we can and can’t do:
- CVE coverage varies by product. OSV.dev has excellent coverage for Node.js, Python, Go, and major databases. Some niche products may have incomplete CVE data.
- We grade technology versions, not your specific dependencies. Our badges tell you “Python 3.12 is healthy.” Tools like Snyk and Dependabot tell you “your specific pip packages have vulnerabilities.” These are complementary, not competing.
- Client library versions are not server versions. If your package.json includes
pg: ^8.11, that’s the npm PostgreSQL client library, not PostgreSQL 8.11. We detect these as indicators (“this project uses PostgreSQL”) but show the version as “unknown” rather than confusing client and server versions.
Questions or Feedback?
If a grade looks wrong, we want to know. File an issue on GitHub or email hello@releaserun.com.
Founded
2023 in London, UK
Contact
hello@releaserun.com