Update Node.js version: commands for every OS

Contents
Updating Node.js sounds trivial until a major version bump silently breaks a native dependency in production. The real risk isn't running the wrong command, it's picking an update path that ignores your OS's package manager conventions or your project's engines field.
Get the command wrong and a routine nvm install can wipe out a working CI pipeline pinned to an EOL release. This guide gives you the exact command for your OS, how to keep npm in sync, and how to confirm nothing broke.
Quick answer: Update Node.js in One command
A stale Node.js LTS release line rarely announces itself. It shows up as a dependency that refuses to install, or a CI job that exits with an EACCES error nobody flagged until deploy. On Linux or macOS with nvm (Node Version Manager) already installed, the fix is one command: nvm install --lts && nvm use --lts. On Windows, nvm-windows or Chocolatey does the same job with a different syntax.
Node.js ships a new major release every six months and retires each line after roughly 30 months of support, per the official Release schedule.
This guide covers the nvm, Homebrew, and Chocolatey install commands, npm sync after the update, rollback to a prior version, and the PATH and permission conflicts that trip up the process.
Check your current Node.js and npm version
Run node -v to verify the minimum required version before touching anything. It prints the exact Node.js build your shell resolves to, which is not always the one you think you installed if multiple version managers are fighting over your PATH.
Pair it with npm -v to see the bundled npm version, since a Node update doesn't always bring the npm you expect. npm ls -g --depth=0 lists every global package and confirms which Node runtime they're registered against, useful before a jump across a major line, because global packages compiled against native bindings can silently break.
Check package.json for an engines field too, and follow the Node.js version requirements specified there. If a project declares "node": ">=22.0.0", that's a semantic versioning constraint, not a suggestion; npm install will warn (and CI will sometimes fail) if your local version falls outside it.
A CI pipeline can stay green for months on a pinned EOL Node version, then fail the week a dependency drops support for it, which is exactly why checking the engines field belongs in code review, not left to surface in production.
Update Node.js on linux (nvm, apt, n, binary)
Nvm (Node Version Manager) is the fastest way to update Node.js on Linux without touching system packages, and it's what we reach for first on any dev machine or CI runner we control. apt/apt-get works too, but Ubuntu's default repos lag behind the Node.js release schedule by months, so you often land on an EOL minor version without realizing it.
Here's the practical breakdown:
| Method | Best for | Tradeoff |
|---|---|---|
| nvm | Local dev, per-project versions | Requires shell config, not system-wide |
| apt/apt-get | Quick installs, matches distro | Stale versions, needs NodeSource repo for current LTS |
| n version manager | Simpler alternative to nvm | No per-shell isolation, root-owned installs by default |
| Binary from nodejs.org | CI images, containers | Manual PATH management |
With nvm, nvm install --lts pulls the active LTS release line, and nvm alias default lts/* sets it as your shell default. Switching for a single project is nvm use 22.
A CI pipeline pinned to an old alias can silently keep running an EOL Node build indefinitely, since nothing forces a re-check unless the install step itself is re-run after a major bump. If you're on apt, add the NodeSource repo before installing, since the Ubuntu/Debian archive rarely tracks current Node.js releases. The n version manager is a lighter option if you want fewer moving parts than nvm but still avoid a root-owned global install that triggers EACCES errors later.
Rolling back is one command with nvm (nvm use <previous version>) or a Docker tag pin; a raw binary install has no built-in rollback path.
Update Node.js on macOS (Homebrew, installer, nvm)
Homebrew is the fastest way to update Node.js on macOS: brew upgrade node pulls whatever version brew.sh currently tags stable, usually landing on the current Node.js LTS release line within days of an official release. Node.js 24 entered Active LTS in October 2025 and is the current Active LTS line; Node.js 22 moved into Maintenance LTS the same month, per the Node.js release schedule.
Run node -v before and after any upgrade to confirm the jump landed.
The tradeoff: Homebrew manages one global Node install, so it collides with nvm if both touch the same binary. A CI runner pinned via Homebrew can silently drift onto an EOL minor version if nobody re-runs the update command for months, and the symptom tends to be flaky tests, not a hard failure, which makes it easy to miss.
For a single machine, download the .pkg installer from nodejs.org instead. It writes to /usr/local, needs an admin password, and skips Homebrew's dependency churn.
Running several projects with different engine fields, install nvm: nvm install --lts fetches the current LTS, nvm alias default lts/* sets it as default. Roll back with nvm use 22 if a dependency breaks.
EACCES errors afterward usually trace to a leftover sudo npm install -g, fix ownership on ~/.nvm rather than sudo again. Volta and asdf handle this permission model more cleanly across machines.
Update Node.js on windows (installer, nvm-windows, chocolatey)
Three paths update Node.js on Windows, and the right one depends on your setup: a single dev machine or a CI runner. For a workstation, nvm-windows gives the cleanest control: nvm install 22.11.0 followed by nvm use 22.11.0 switches the active Node version without touching your system PATH manually.
The Windows installer (.msi) from nodejs.org is the simplest option for a one-off update, but it overwrites your Node install in place. It doesn't let you keep multiple versions side by side, which is fine for a laptop but a liability on a build agent where a rollback needs to be instant.
Chocolatey package manager is a solid choice for CI runners. choco upgrade nodejs-lts -y is scriptable, idempotent, and fits into the same provisioning step as your other build tools, which matters when a runner image gets rebuilt weekly. A pipeline pinned to an EOL Node line can fail silently for weeks if nobody rebuilds the base image; Chocolatey in the provisioning script catches that on the next scheduled rebuild instead.
After any update, run node -v and check where node to confirm the PATH environment variable points at the version you intended, not a stale entry from a previous .msi install. If something breaks, nvm-windows makes rollback a one-line command: nvm use 22.11.0 (LogRocket: How to switch Node.js versions). On Docker-based CI, pin the base image tag instead.
Volta is worth a look if your team manages Node versions per-project rather than per-machine.
Do you need to update npm separately?
Yes, in practice, because Node.js bundles a fixed npm version that often lags behind npm's own release line, so bumping Node from 18 to 22 does not guarantee the newest npm.
Run npm install -g npm@latest right after any Node update to decouple the two. This is documented in npm's own CLI documentation as the standard way to pin npm independent of the Node runtime.
The package.json engines field is where this actually bites. If you declare "engines": {"node": ">=22.0.0", "npm": ">=10.0.0"} and run with --engine-strict, a stale npm binary throws on install instead of warning (npm Docs). That's a fast, loud failure mode, which is preferable to the alternative: a runner pinned to an EOL Node minor that installs fine until a fresh clone hits a dependency that's dropped support for it.
Check both versions with node -v and npm -v before you trust either.
Verify the update and fix common errors
Run node -v immediately after any update to learn which version is now active. If it still prints the old version, the shell is reading a stale binary from PATH rather than the one nvm just installed, usually because a system Node install (from an OS package manager or an old Homebrew formula) sits earlier in the search order.
Fix it by checking which node, reordering PATH in your .bashrc or .zshrc, and confirming nvm alias default points at the version you expect. On Windows, nvm-windows resolves this the same way through its own shim, not the system PATH.
EACCES permission error during npm install -g is the other recurring failure. It shows up when npm was first installed with sudo and now owns global folders as root, and it's easy to mistake for something else entirely if it surfaces on a CI runner mid-deploy rather than on a local machine where the cause is obvious.
The fix: switch to nvm (or Volta, or asdf) so Node and npm install into a user-owned directory, never global root paths.
If the new version breaks a dependency, roll back fast: nvm install 22 && nvm alias default 22, or pin a Docker base image tag to the previous LTS line, while you read the incompatible package's engine field for a permanent fix.
LTS vs current, and rolling back a bad update
Pick the Node.js LTS release line for anything running in production, and reserve Current for experiments with V8 features you can't wait a year for. LTS gets 30 months of support, six months of active development, then eighteen months of maintenance, according to the Node.js release schedule.
Current ships new engine features every six months but loses support the moment the next Current version lands, so pinning a CI pipeline to it is a bet you'll re-run this whole update process every quarter. If you need help planning upgrades or building production-grade applications on the right release line, Netguru's expert Node.js development services can guide your team's strategy.
Track both lines against the Node.js EOL schedule on endoflife.date rather than trusting memory. A pipeline can stay pinned to an EOL release for a long time without anything visibly breaking, silently missing patched CVEs the whole time, because nothing forces a re-check unless someone ties a calendar reminder to the release line.
If the update breaks the app, roll back fast. Run nvm install <previous-version> then nvm alias default <previous-version> to reset the shell default in seconds; nvm-windows takes the same two commands from an administrator prompt. In Docker, pin the base image tag to a specific LTS version (e.g. node:22-alpine, not node:latest) so a bad bump never reaches a running container unnoticed.
Volta and asdf handle version switching with per-project files instead of shell state, worth a look once a team manages Node versions across many repos. Pinning an .nvmrc file to the current LTS number keeps node -v output consistent across every developer's machine and every CI runner.
Why Node.js EOL matters for security
The Node.js EOL schedule determines when a release line stops getting security patches, not when it stops working. That gap is the trap: an EOL version keeps running fine until a CVE lands with no fix behind it.
A pipeline pinned to an EOL version months past its cutoff can keep passing builds and shipping deploys the entire time, with nothing crashing, which is exactly the problem with silent EOL drift: it usually takes a routine audit, not a failure, to catch it.
According to the Node.js release schedule, each major version gets roughly 30 months of support before entering EOL, and endoflife.date tracks the exact cutoff dates per line. Cross-check both before you assume a version is still covered.
Run node -v against that schedule quarterly, not just after an incident. Treat an EOL Node version the same way you'd treat an EOL OS image: a compliance and attack-surface issue, not a deferred backlog item.
Nvm vs n vs volta: Which version manager to use
Nvm (Node Version Manager) remains the default choice for most Linux and macOS teams because it manages multiple Node.js versions per shell session and supports an .nvmrc file for per-project pinning. The n version manager is a lighter alternative, fewer subcommands, faster install, no shell function wrapping, but it lacks nvm's per-directory version switching, which matters once a monorepo mixes Node 18 and Node 22 services.
Volta and asdf solve a different problem: automatic version switching without sourcing a shell script on every cd. Volta pins versions at the project level and enforces them for npm too, which avoids the classic "works on my machine" mismatch that shows up when one engineer's global npm install drifts from what CI expects.
| Tool | Best for | Weakness |
|---|---|---|
| nvm | Linux/macOS, multi-project switching | Slower shell startup, no native Windows support |
| n version manager | Simple single-version workflows | No per-project auto-switch |
| Volta | Teams enforcing pinned Node + npm versions | Smaller community, less battle-tested on Windows |
| asdf | Polyglot stacks (Node, Ruby, Python in one tool) | Extra plugin layer to maintain |
On Windows, skip nvm entirely and use nvm-windows or Chocolatey, nvm's shell script doesn't port cleanly. Defaulting to nvm with an .nvmrc file gives reproducible builds for most teams, with Volta as the better fit once a project needs strict npm-version enforcement across a distributed team.
FAQ: Node.js update questions
How do I check my current Node.js and npm version?
Do I need to update npm separately from Node.js?
How do I fix node -v still showing the old version after updating?
How do I downgrade Node.js if an update breaks my app?
nvm install <previous-version> && nvm use <previous-version>, or pin the older tag in your Docker base image. This is the fastest fix when a dependency breaks against a new engine field, say after jumping to v24. Keep an .nvmrc per project so switching stays one command.
Should I use LTS or current release line?
What's the chocolatey command to update Node.js?
How does nvm compare to n and volta?
Keep Node.js updated without breaking your pipeline
Running an EOL Node.js line is a silent risk: no security patches, no bugfixes, just a pipeline waiting to fail during a routine npm install. Teams that treat nvm switches and npm updates as a scheduled task, not a fire drill, avoid the kind of multi-hour rollback that follows an unplanned major bump breaking a lockfile.
If your CI runners still reference an EOL Node version or you want a second opinion on your nvm/Docker rollback strategy, talk to our team. We help engineering teams keep dependencies current without downtime, so releases stay predictable and support stays consistent across every environment. Beyond one-off fixes, our ongoing software maintenance support keeps your Node.js stack patched, monitored, and running smoothly long after the initial upgrade.
