Node.js Release Lines & LTS
Node.js ships new versions on a predictable cadence, and understanding that cadence is the difference between a calm, secure production deployment and an emergency upgrade scramble. Every Node version follows a defined lifecycle that moves from cutting-edge “Current” to stable “Active LTS” to security-only “Maintenance,” and finally to End-of-Life. This page explains how the release model works, what even and odd version numbers mean, and how to choose the right line for a given project.
The release lines
Node.js maintains several parallel “release lines” at any moment. Each line corresponds to a major version (the first number in 20.11.1) and progresses through well-defined phases. The phase a line is in tells you exactly what kind of changes you can expect to receive.
| Phase | What you get | Typical duration | Production use |
|---|---|---|---|
| Current | New features, breaking changes, performance work | ~6 months | Experiments only |
| Active LTS | Bug fixes, security patches, non-breaking backports | ~12 months | Recommended |
| Maintenance LTS | Critical bug fixes and security patches only | ~18 months | Acceptable, plan to upgrade |
| End-of-Life | Nothing — no patches, no security fixes | — | Do not use |
A brand-new major release starts life as Current. During this phase the version is fully supported and receives new features, but APIs may still change and behavior can break between minor releases as the line stabilizes.
Even vs odd version numbers
The single most important rule of the Node release model: only even-numbered major versions become LTS. Odd-numbered releases (19, 21, 23) are intentionally short-lived. They exist to land riskier features, ship the newest V8 engine, and gather feedback — but they are dropped after roughly six months and never receive long-term support.
Never run an odd-numbered Node version in production. Versions like 21 or 23 reach End-of-Life in about six months and stop receiving security patches. Always target the latest even LTS line for anything you deploy.
You can confirm which line you are on directly from the runtime.
import process from 'node:process';
console.log(`Node version: ${process.version}`);
console.log(`Major release: ${process.versions.node.split('.')[0]}`);
console.log(`V8 engine: ${process.versions.v8}`);
Output:
Node version: v22.11.0
Major release: 22
V8 engine: 12.4.254.21-node.21
The ~30 month lifecycle
An even-numbered release is supported for roughly 30 months in total. Here is the journey of a typical LTS line:
- Current (~6 months) — Released in the spring of its year (e.g. Node 22 in April). It is the latest and greatest but still hardening.
- Active LTS (~12 months) — In October of the same year, an even release is promoted to Active LTS and assigned a codename (Hydrogen, Iron, Jod, etc.). This is the recommended target for new and existing production apps.
- Maintenance LTS (~18 months) — Once a newer LTS line takes over, the older one drops to Maintenance and receives only critical and security fixes.
- End-of-Life — After ~30 months total, the line is retired. No further releases of any kind are published.
Because a new even line enters Active LTS every October, there is always an overlap window where two LTS lines are supported simultaneously — giving teams a comfortable runway to migrate.
# List the LTS codenames and their schedule (requires the npm package)
npx envinfo --system
node --version
Output:
v22.11.0
Picking a version for production
For nearly every application the answer is the latest Active LTS release. It has the broadest ecosystem compatibility, the longest remaining support window, and a stable API surface. Reach for Current only when you specifically need a feature that has not yet been backported, and accept that you will need to upgrade more frequently.
You can pin the required version in package.json so that CI and teammates use a compatible runtime.
{
"name": "my-service",
"version": "1.0.0",
"type": "module",
"engines": {
"node": ">=20.0.0"
}
}
A .nvmrc file lets tools like nvm and fnm select the exact line automatically.
echo "22" > .nvmrc
nvm use
Output:
Found '/app/.nvmrc' with version <22>
Now using node v22.11.0 (npm v10.9.0)
Match your CI matrix to the Node lines you actually support. Testing against both the current Active LTS and the previous Maintenance LTS catches upgrade regressions before your users do.
You can also guard against an unsupported runtime at startup, which prevents subtle failures on machines running an old or odd version.
import process from 'node:process';
const major = Number(process.versions.node.split('.')[0]);
if (major < 20 || major % 2 !== 0) {
console.error(`Unsupported Node ${process.version}. Use an even LTS line (>=20).`);
process.exit(1);
}
console.log(`Running on supported Node ${process.version}`);
Output:
Running on supported Node v22.11.0
Best practices
- Deploy on the latest even-numbered Active LTS release; treat odd versions as throwaway preview builds.
- Upgrade to the next LTS line during its overlap window — don’t wait until your current line hits End-of-Life.
- Pin the supported range with
enginesinpackage.jsonand a.nvmrc(or.tool-versions) file so every environment agrees. - Run your CI test matrix against both the current and previous LTS lines to catch breaking changes early.
- Track the official release schedule and subscribe to Node.js security release announcements.
- Avoid building production on Current unless you genuinely need an unreleased feature, and budget time for its faster upgrade cadence.