Every Node.js major line reaches end of life on a published date, and from that day it gets no security releases, even for flaws the project fixes in newer lines. Node.js 18 and 20 are already past end of life, Node.js 22 ends on 30 April 2027, and from Node.js 27 the project has moved to one major release a year with every line becoming LTS. This guide gives the official dates, explains the new schedule, and shows how to find old Node.js in servers, container images, serverless functions, CI runners and bundled software, then how to plan, test and roll back the upgrade. It is for platform, application security and vulnerability management teams. For the cross-language view (Java and Python too), see the End-of-Life Language Runtimes guide; this page goes deeper on Node.js only.
This is an independent guide from NHI Mgmt Group, based on the Node.js project's public documentation as of November 2026. It is not sponsored or reviewed by the Node.js project or the OpenJS Foundation. Release dates can change, so confirm them against the project's current release schedule.
Key takeaways
- Node.js 22, 24 and 26 are the supported lines. As checked on 8 November 2026, 22 and 24 are in Maintenance LTS, 26 is Active LTS, and 27 is in a new Alpha phase that is not for production.
- End of life means no fixes at all. The project states that EOL lines receive no new releases, so when a vulnerability fixed in a supported line also affects an EOL line, applications on that line stay exposed.
- The schedule changed with Node.js 27. One major release a year, a six month Alpha, six months as Current, then 30 months of LTS, for 36 months from first Current release to end of life.
- Containers hide old runtimes. A pinned base image tag such as
node:18-alpinekeeps shipping an EOL runtime in every rebuild; read the image'sNODE_VERSIONand SBOM, not just the application code. - Native addons and old dependencies are the usual blockers. Addons built on Node-API are designed to run on later majors without recompilation; addons built against V8 or NAN APIs directly usually need rebuilding or replacement.
What is changing and why
The Node.js Release Working Group runs every major line through fixed phases. Up to and including Node.js 26, a new major shipped every six months: even numbers in April, odd numbers in October. Odd lines were unsupported after six months; even lines moved to Active LTS for 12 months and then Maintenance for 18 months, roughly 30 months of LTS in total. The project's guidance is direct: production applications should only use Active LTS or Maintenance LTS releases.
In its announcement "Evolving the Node.js Release Schedule" (page last updated 10 March 2026), the project explained the move to one major release a year from Node.js 27. The reasons it gives: odd releases saw little adoption, the odd and even split confused newcomers, enterprises want a predictable plan, and a mainly volunteer team found backporting security fixes across four or five lines hard to sustain. Under the new model:
- Alpha (6 months, October to March): signed and tagged prereleases such as
27.0.0-alpha.1, tested with CITGM, for library authors and CI. API and ABI may change; not for production. - Current (6 months, April to October): the first semver-major release, then stabilisation.
- LTS (30 months): every line is promoted to LTS in October and, per the Release Working Group README, stays Active LTS for the whole 30 months with no separate Maintenance phase.
- Version numbers follow the year: 27.0.0 in 2027, 28.0.0 in 2028.
Node.js 26 is the last line on the old model. The project says the schedule may be amended and names schedule.json in the nodejs/Release repository as the authoritative source for dates.
Official timeline and current status
Dates below are from the Node.js Release Working Group schedule and the nodejs.org Previous Releases page, both checked on 8 November 2026. The project marks all dates as subject to change.
| Line (codename) | Initial release | Active LTS start | Maintenance start | End of life | Status on 8 Nov 2026 |
|---|---|---|---|---|---|
| 16 (Gallium) | 2021-04-20 | 2021-10-26 | 2022-10-18 | 2023-09-11 | EOL |
| 18 (Hydrogen) | 2022-04-19 | 2022-10-25 | 2023-10-18 | 2025-04-30 | EOL |
| 20 (Iron) | 2023-04-18 | 2023-10-24 | 2024-10-22 | 2026-04-30 | EOL |
| 21, 23, 25 (odd) | October of each year | None | April following | 2024-06-01, 2025-06-01, 2026-06-01 | EOL |
| 22 (Jod) | 2024-04-24 | 2024-10-29 | 2025-10-21 | 2027-04-30 | Maintenance LTS |
| 24 (Krypton) | 2025-05-06 | 2025-10-28 | 2026-10-20 | 2028-04-30 | Maintenance LTS |
| 26 (Lithium) | 2026-05-05 | 2026-10-28 | 2027-10-20 | 2029-04-30 | Active LTS |
| 27 | Alpha from 2026-10-28; Current from 2027-04-22 | LTS from 2027-10-20 | None (new model) | 2030-04-30 | Alpha |
Two practical readings of this table. First, anything on 20 or older is already unsupported upstream. Second, 22 has under six months left: a team that starts an upgrade from 22 now should target 24 or 26, not plan a second hop within a year. Commercial support for lines past Maintenance is offered by partners of the OpenJS Ecosystem Sustainability Program listed on the Node.js End-of-Life page, and the project describes such support as a temporary measure while you upgrade.
Who and what is affected
Node.js turns up in more places than application servers. Build the scope list before scanning.
| Where Node.js runs | How the version is set | Why it is missed |
|---|---|---|
| Linux and Windows servers, VMs | OS package, NodeSource style repository, tarball, version manager (nvm, fnm, volta) | Several versions installed side by side; the service unit points at an old one |
| Container images | Base image tag (node:20-bookworm-slim), or a binary copied into a distroless or custom base | Pinned tags rebuild cleanly for years; multi-stage builds hide the runtime layer |
| Serverless functions | Platform runtime identifier, for example nodejs18.x on AWS Lambda | Functions deployed once and never redeployed; platform deprecation dates differ from upstream |
| CI runners and build tools | .nvmrc, .node-version, CI setup actions, self-hosted runner images | Not in production inventories, yet they hold publish tokens and cloud credentials |
| Desktop and vendor software | Bundled runtime inside Electron apps, appliances, agents and admin consoles | Only the vendor can update it; appears as a vendor product, not as Node.js |
| Developer laptops | Version managers, global installs | Local builds produce artefacts that differ from CI |
Serverless platforms publish their own deprecation calendars, which can trail the upstream date; see the AWS Lambda Runtime Deprecation guide. Running past the upstream date on a managed platform still means running a line the Node.js project no longer patches.
Finding affected systems and identities
Combine declared versions (what the code asks for) with observed versions (what actually runs). Neither alone is reliable.
- Read the manifests in every repository. Collect the
engines.nodefield inpackage.json,.nvmrcand.node-version, the Node version in CI workflow files, and everyFROM node:line in Dockerfiles. Note that npm treatsenginesas advisory and only warns unless theengine-strictconfig is set to true. - Inspect container images in registries and clusters. The official Node.js images set an environment variable, for example
NODE_VERSION=26.13.0, readable from image metadata without running the container. For custom images, generate an SBOM and look for the node binary component and version. Inventory images actually running in each cluster, not only what is in the registry. See the Container Image Security Guide and the SBOM Guide. - Watch the floating tags. The official images document that
node:ltsselects the Active LTS line and that a tag with no version, such asnode:slim, selects the Current release. Floating tags move across majors on rebuild, so a rebuild can change the runtime without a code change. Pin the major deliberately and update it on purpose. - Query hosts and endpoints. Use your endpoint management or software inventory to report installed Node.js versions and the path each service unit or scheduled task executes. At runtime,
process.versiongives the version andprocess.release.ltsgives the LTS codename (it is undefined on non-LTS lines), which applications can report to telemetry. - List serverless runtimes. Export the runtime identifier of every function in every account and region from the cloud provider's inventory or configuration service.
- Ask vendors. For appliances and packaged software, request the bundled Node.js version and the vendor's upgrade date in writing, and record it in the asset register. See the Asset Inventory and CMDB Security Guide.
Where identity fits: old build images and self-hosted runners often carry long-lived npm publish tokens, registry credentials and cloud keys. When you find an EOL runner, rotate the secrets it held and move publishing to short-lived credentials. See the npm Tokens Security Guide and the npm Trusted Publishing and Provenance Guide.
Migration options
| Option | When it fits | Trade-off |
|---|---|---|
| Upgrade straight to 26 (Active LTS, EOL 2029-04-30) | Maintained services with reasonable test coverage | Biggest jump from 18 or 20; longest runway and fewest future hops |
| Upgrade to 24 (EOL 2028-04-30) | Large codebases, dependencies not yet tested on 26 | Smaller change; another upgrade due within about 18 months |
| Stay on 22 short term | Already on 22 with an upgrade scheduled before April 2027 | Under six months left; only a stopgap |
| Commercial extended support for an EOL line | Systems that cannot change before EOL, with a funded replacement date | Cost; the project calls it temporary; fixes come from the provider, not upstream |
| Retire or isolate | Unused services, vendor software with no upgrade path | Needs ownership decisions; isolation reduces exposure but does not remove it |
Common upgrade blockers and how to handle them:
- Native addons: the Node.js documentation describes Node-API as ABI stable across versions, so addons built on it are intended to run on later majors without recompilation. Addons that use V8 or NAN interfaces directly generally need a rebuild, and abandoned ones need replacement. List every package with a native build step early.
- Deprecated APIs: Node.js has four kinds of deprecation: Documentation-only, Application, Runtime and End-of-Life. Run tests on the current line with
--pending-deprecationto surface warnings that would otherwise be silent, and--throw-deprecationin CI to make them fail builds. - Frozen dependencies: the project notes that packages drop support for EOL lines over time, so a long-stalled upgrade usually means upgrading frameworks too. Tie the runtime upgrade to your dependency update process; see the Dependency Update Automation Guide.
- Operating system and libraries: the project warns that EOL releases may stop linking with newer shared libraries, which can block OS updates. Upgrade the base image OS and the runtime together.
- Vendor packaged runtimes: you cannot upgrade them yourself. Track the vendor's date and apply compensating controls until then.
Testing and rollback
- Add the target line to CI first. Run the full test suite on both the current and target lines in a matrix, with
--pending-deprecationon. Library maintainers can add the Alpha line to CI, as the project recommends, to catch breakage early. - Pin exact versions. Set
engines.node,.nvmrcand the image tag to the target major (and pin image digests for production builds), and considerengine-strict=truein project config so installs fail on the wrong runtime. - Rebuild, do not patch in place. Build new images and function packages, regenerate the SBOM, and rescan before deployment.
- Roll out in rings. Non-production, then a canary slice of production with error rate, latency and memory compared against the old version, then the rest.
- Keep a rollback artefact. Retain the previous image digest or function version for a fixed window, and keep the rollback path tested. Rollback restores an EOL runtime, so set a firm date to retry and record it as an exception.
- Close the loop. Remove the old runtime from hosts and registries after the window, so it cannot be redeployed by accident.
Risks of doing nothing
- Permanent known vulnerabilities: once a fix is published for supported lines, details are public and EOL lines stay unpatched. Internet-facing services become candidates for MITRE ATT&CK T1190 Exploit Public-Facing Application.
- Supply chain drag: pinned old runtimes keep old dependency trees, which slows response to a malicious or vulnerable package (T1195.002 Compromise Software Supply Chain). See the Malicious Package and Dependency Confusion Guide.
- Audit findings: the project notes many audits prohibit unmaintained runtimes, and NIST SP 800-53 SA-22 Unsupported System Components expects replacement or documented alternative support.
- Forced emergency upgrades: a serious advisory or a platform deprecation date turns a planned change into an outage-risk change under time pressure.
| Framework | Reference | How it applies |
|---|---|---|
| NIST CSF 2.0 | ID.AM-02, ID.RA-01, PR.PS-02 | Inventory software, record vulnerabilities, maintain and replace software by risk |
| NIST SP 800-53 Rev 5 | CM-8, SA-22, SI-2, RA-5 | Component inventory, unsupported components, flaw remediation, scanning |
| CIS Controls v8.1 | 2.2 Ensure Authorized Software is Currently Supported | Unsupported software flagged and given a documented exception or removal |
| ISO/IEC 27001:2022 Annex A | 8.8 Management of technical vulnerabilities | EOL runtimes treated as a vulnerability with an owner and deadline |
Metrics that show progress: percentage of running workloads on a supported line; count of images and functions on EOL lines, trending to zero; days until the next EOL date for each line in use; number of open SA-22 exceptions and their age; percentage of repositories with a pinned, supported engines.node.
Practitioner checklist
- Record the official end of life date for every Node.js line in use, with the date you checked
schedule.json. - Scan repositories for
engines.node,.nvmrc,.node-version, CI Node settings andFROM node:lines. - Inventory running container images and read
NODE_VERSIONor SBOM data for each. - Export serverless runtime identifiers across all accounts and regions.
- Replace floating image tags with a pinned major, and pin digests for production.
- Move anything on 22 or older to 24 or 26 before 30 April 2027.
- Identify native addons and confirm Node-API support or a replacement.
- Run CI on the target line with
--pending-deprecationbefore cutover. - Rotate secrets held by retired build images and runners.
- Track vendor-bundled runtimes with written vendor dates and a documented SA-22 exception.
Standards and references
- Node.js: Node.js Releases
- Node.js: End-of-Life
- Node.js Release Working Group: Release schedule and phases
- Node.js: Evolving the Node.js Release Schedule
- Node.js: Node-API documentation
- Node.js: Deprecated APIs
- Node.js: Official Docker images (docker-node)
- NIST: SP 800-53 Rev 5 Security and Privacy Controls
Related NHI Mgmt Group resources: End-of-Life Language Runtimes · Unsupported PHP versions · Node.js Security Guide · AWS Lambda Runtime Deprecation · CIS Control 7 Continuous Vulnerability Management Guide