Understanding the Node.js LTS and Release Lifecycle
Node.js ships a new major version every six months -- one in April, one in October. The catch: not all releases are created equal. Odd-numbered major versions (the October releases) are Current releases that live for roughly six to eight months and are never promoted to LTS. Even-numbered major versions (the April releases) are the ones that matter for production -- they enter Long-Term Support (LTS) in October of the same year and receive official support for 30 months total.
Those 30 months break into two phases:
| Phase | Duration | What Is Covered |
|---|---|---|
| Active LTS | 18 months | Bug fixes, security patches, performance improvements, documentation updates |
| Maintenance LTS | 12 months | Critical bug fixes and security patches only -- no new features |
After Maintenance ends, the release line becomes End of Life. The Node.js project publishes a public release schedule at nodejs.org/en/about/previous-releases that maps every major version to its exact support window. The dates shown in the release table above come directly from that schedule.
In practice, most engineering teams target the current Active LTS release for production. If you are on a Maintenance version, you should already be planning your upgrade -- you are one disclosed CVE away from being on unsupported software.
What Are the Real Risks of Running an EOL Node.js Version?
Running an end-of-life Node.js version in production is not a theoretical problem -- it has concrete, day-to-day consequences for every team doing it.
No security patches. Node.js bundles V8, OpenSSL, libuv, and other dependencies. When a CVE is disclosed in any of these components, the fix ships to supported versions only. EOL versions stay vulnerable. Because Node.js is a runtime -- meaning it executes arbitrary code, handles network traffic, and processes user input -- an unpatched TLS or parser vulnerability is directly exploitable.
npm ecosystem drift. Popular packages regularly drop support for EOL Node.js versions. You will start seeing install warnings, then hard failures. Native addon packages (those compiled with node-gyp) are particularly aggressive about this -- they tie directly to Node.js's ABI version, and a new major release breaks compatibility immediately without a recompile.
Toolchain incompatibility. CI runners, Docker base images, serverless platforms, and PaaS providers stop shipping EOL Node.js images. You end up maintaining custom base images just to stay on an unsupported runtime -- exactly the opposite of reducing maintenance overhead.
No bug fixes. Any runtime bug you hit -- memory leak, stream behavior, event loop quirk -- will not be fixed upstream. You are on your own.
What Actually Happens When Node.js Support Ends?
When a Node.js major version reaches End of Life, the Node.js project stops publishing security releases for it. The GitHub repository remains public and the source code does not disappear, but no one from the project is responsible for it anymore.
The practical downstream effects happen quickly:
- The official Docker Hub
nodeimage stops receiving updates for that tag. The image goes stale and accumulates OS-level vulnerabilities on top of the Node.js ones. - Vulnerability scanners (Snyk, Dependabot, Trivy) start flagging the Node.js version itself as a finding, not just your dependencies. This creates noise in security reviews.
- Cloud providers (AWS Lambda, Google Cloud Functions, Azure Functions) deprecate the runtime and eventually remove it from the available list, giving you a forced upgrade deadline.
- The
npmCLI starts printing warnings when it detects an unsupported Node.js version at install time.
The Node.js ecosystem moves faster than most runtimes. A version that was current eighteen months ago can feel very far behind today. Most teams find that staying within one or two major versions of the current LTS is the sustainable baseline -- it keeps upgrade steps small and tooling compatible.
How To Check Your Node.js Version
The fastest way to check your Node.js version on any platform:
node --version
# example output: v22.14.0
# Also check bundled npm version
npm --version
# Check the full environment detail
node -e "console.log(process.versions)"
If you manage multiple Node.js versions across projects, a version manager gives you both the version check and the switch:
# With nvm (Node Version Manager)
nvm current # show active version
nvm ls # list all installed versions
nvm ls-remote # list all available versions
nvm use --lts # switch to latest LTS
# With fnm (Fast Node Manager, cross-platform)
fnm current
fnm list
fnm use --lts
In production environments, check the Node.js version programmatically at startup and log it. This makes it trivial to audit which version each service instance is running when reviewing deployment logs. You can also inspect the process.release.lts property -- it returns the LTS codename string (e.g., "Jod") if the current runtime is an LTS version, or false if it is not.
// Log at startup to make version auditing easy
console.log({
nodeVersion: process.version,
lts: process.release.lts,
platform: process.platform,
});
FAQ
Q1: What is the difference between a Current and an LTS release?
Current releases are six-month experimental tracks where new features land first. They are fine for personal projects or evaluating what is coming next, but they are not suitable for production because they do not receive extended support. LTS releases (even-numbered majors) are what most teams should run in production -- they get 30 months of security and bug fix updates on a predictable schedule.
Q2: How often should I upgrade Node.js in production?
A reasonable cadence is: follow Active LTS releases, and give yourself a few months after a new LTS lands to evaluate it before migrating. That typically means upgrading once every two to three years for conservative teams, or tracking each Active LTS window for teams that want the latest performance and V8 improvements. The key signal is the transition from Active to Maintenance -- that is when you should have an upgrade already tested and scheduled.
Q3: Does my .nvmrc file guarantee the same Node.js version in CI as locally?
Only if your CI runner is also configured to read .nvmrc or .node-version. Most CI platforms (GitHub Actions, CircleCI, GitLab CI) have built-in Node.js setup actions that respect these files when you specify node-version: 'file'. Without that, the CI runner uses whatever Node.js version it happens to have installed -- which may drift over time. Always pin explicitly in both local and CI configurations.
Q4: Can I run multiple Node.js versions on the same machine?
Yes, and for most development environments you should. Tools like nvm (macOS/Linux), nvm-windows, fnm, or volta let you install and switch between any number of Node.js versions in a single shell command. This lets you test upgrades without affecting other projects and run different services that have different version requirements on the same machine.
Q5: Does Node.js version affect native addon compatibility?
Yes -- this is one of the most common upgrade pain points. Native addons (packages with C/C++ code compiled via node-gyp) are compiled against a specific Node.js ABI version, which changes with each major release. When you upgrade Node.js, any native addon must be recompiled for the new ABI. Run npm rebuild after upgrading Node.js to recompile installed native addons. Packages that use Node-API (formerly N-API) are more resilient -- they target a stable ABI layer and typically do not need recompilation across Node.js major versions.
