Node.js 18 End of Life: Upgrade Guide to 20/22 LTS
Node.js 18 reached end of life on April 30, 2025. And here is the part many teams planning "the Node 18 upgrade" in 2026 miss: the obvious next stop, Node.js 20, is also dead — it reached end of life on April 30, 2026. If you are still shipping on Node 18 today, the upgrade target is Node 22 at minimum, and preferably 24 or 26. This guide covers what stopped, what actually breaks, and how to land the jump cleanly.
Current Status: What Stopped and When
When a Node.js line reaches end of life, the project stops shipping everything for it: security releases (including patches for vulnerabilities in the bundled OpenSSL and V8), bug fixes, and new binaries. There is no maintenance mode after EOL — the line is simply finished.
| Node.js Version | Support Ended / Ends | Status |
|---|---|---|
| Node.js 16 | Sep 11, 2023 | EOL |
| Node.js 18 | Apr 30, 2025 | EOL |
| Node.js 20 | Apr 30, 2026 | EOL |
| Node.js 22 | Apr 30, 2027 | Supported |
| Node.js 24 | Apr 30, 2028 | Supported |
| Node.js 26 | Apr 30, 2029 | Supported |
The pattern is worth internalizing: even-numbered lines get long-term support and die on April 30 of their final year. Every version's exact dates are on our Node.js lifecycle page.
Who Is Affected
Node 18 hides in more places than package.json suggests:
- Docker images — anything built
FROM node:18, including base images maintained by other teams. - Serverless and PaaS runtimes — functions pinned to a Node 18 runtime keep running after providers deprecate the option, quietly unpatched.
- CI/CD pipelines and build tooling — runners and build containers pinned to 18 long after production moved on (or vice versa).
- Electron-style bundled runtimes and internal CLIs — Node versions frozen at build time.
- Backend services with native dependencies — the teams most likely to have deferred the upgrade, because it was never "just" a version bump for them.
Migration Paths, Ranked by Effort
Path 1 — Direct runtime bump (most applications)
For a typical service with maintained dependencies: switch the version in .nvmrc/package.json engines and the Dockerfile, delete node_modules and the lockfile's build artifacts, reinstall, run the suite. Jump straight to Node 22 or 24 — an 18→20→22 staircase just multiplies the testing effort, and lands you on a version (20) that is already EOL.
Path 2 — Dependency-led upgrade (native modules and old frameworks)
If the app uses native addons (crypto, image processing, database drivers) or a framework that pins engine ranges, upgrade the blockers first on Node 18, then bump the runtime. Modern native modules using N-API/Node-API generally carry across versions unchanged; older ones compiled against specific V8 internals must be updated or replaced. This is a one-to-few sprint effort, dominated by the worst dependency.
Path 3 — Re-platform the runtime (pinned serverless/PaaS estates)
Where the Node version is a platform setting rather than a Dockerfile line, the migration is a redeploy per function or app onto the provider's newer runtime. Effort scales with the number of functions and how much per-function testing each needs — mechanical, but tedious at fleet scale.
Path 4 — Extended support as a bridge
For applications genuinely stuck on 18 — usually an abandoned native dependency or a frozen vendor bundle — paid patching exists; see below.
Step-by-Step Migration Checklist
- Find every Node 18 (and 20) runtime — Dockerfiles,
.nvmrc, CI configs, serverless runtime settings, and base images owned by other teams. - Pick the target. Node 22 for the shortest jump; 24 or 26 for a longer runway before the next forced upgrade.
- Audit engines and native modules. Check
enginesconstraints across the dependency tree and identify native addons; upgrade or replace the ones without support for the target line. - Upgrade in a branch: bump the runtime everywhere at once (app, Docker, CI) so tests run against reality, reinstall from a clean state, and rebuild native modules.
- Run the full suite plus a smoke test under load. Watch for deprecation warnings on startup — they are the changelog telling you what breaks next major.
- Stage, then roll production gradually with the old image tagged and ready for rollback.
- Update the floor. Set
engines.nodeto the new minimum and pin CI to it, so the fleet can't silently drift back.
Common Pitfalls (What Actually Breaks)
- Native addons. The single most common blocker. A module compiled against Node 18's ABI fails to load on 22+ until rebuilt — and if the package is abandoned, rebuilding isn't enough. Identify these before you schedule the cutover.
- The forgotten Dockerfile. Production gets upgraded; the cron container, the migration job image, or the CI runner stays on
node:18for another year. Grep the whole org, not the main repo. - Engine-range lockouts. Dependencies with strict
enginesconstraints fail installs on the new runtime even when the code would run fine — surfacing as CI failures that look like your fault. - Deprecations that came due. APIs that only warned on Node 18 can be removed or behave differently in later lines. Treat startup warnings on the old version as a pre-migration work list.
- OpenSSL-sensitive code. Node lines bundle their own OpenSSL; TLS defaults and legacy-algorithm behavior can shift between majors. Anything doing unusual crypto or talking to legacy TLS endpoints deserves explicit testing.
If You Can't Migrate Yet
If a hard dependency keeps you on Node 18 past every deadline, commercial extended-support vendors ship security patches for EOL Node.js lines as a paid bridge — turning an unpatched runtime into a patched-but-legacy one while you finish the real fix. We compare the options on our extended support vendors page. As with every bridge: write down the exit date, and spend the purchased time on Path 2, not on getting comfortable.
Frequently Asked Questions
When did Node.js 18 reach end of life?
April 30, 2025. No security patches, bug fixes, or OpenSSL updates ship for it since. Node 16 ended September 11, 2023; Node 20 followed on April 30, 2026.
Should I upgrade Node 18 to Node 20 or Node 22?
Skip 20 — it went EOL on April 30, 2026. Target Node 22 (supported until April 30, 2027) at minimum; prefer 24 (to April 2028) or 26 (to April 2029) for more runway.
What breaks when upgrading from Node 18 to a newer LTS?
Native addons needing rebuilds, dependencies with strict engine ranges, removed deprecated APIs, OpenSSL/TLS behavior shifts, and forgotten node:18 Docker images and CI runners.
Can I jump directly from Node 18 to Node 22 or 24?
Yes. Bump the runtime in a branch, reinstall and rebuild dependencies, run the suite, and fix what surfaces. No intermediate majors required.
Is there extended support for end-of-life Node.js versions?
Yes — commercial extended-support vendors patch EOL Node.js lines, including 18, as a paid bridge. See our extended support vendors comparison.