Introduction
If you've ever cloned a project and immediately hit a wall because your Node version doesn't match what the project needs, you already know why nvm exists. It's one of those tools that seems optional until you actually need it, and then it becomes essential.
What is nvm and Why Should You Care?
nvm (Node Version Manager) lets you install and switch between multiple Node.js versions on the same machine. Think of it like having different versions of a game installed you can play whichever one you need without uninstalling the others.
Here's why this matters: different projects often require different Node versions. A legacy project might need Node 14, while your new side project runs on Node 20. Without nvm, you'd be stuck manually uninstalling and reinstalling Node every time you switch projects. With nvm, it's just one command.
Installing nvm
The installation process differs slightly between operating systems.
On macOS and Linux
Open your terminal and run:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
Or if you prefer wget:
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
After installation, close and reopen your terminal, or run:
source ~/.bashrc # or ~/.zshrc if you use zsh
Verify it worked:
nvm --version
On Windows
Windows users need a different tool called nvm-windows. Download the installer from the nvm-windows releases page and run it. The commands are mostly the same, but it's a separate project.
💡 Tip: If you're on Windows and use WSL2, you can install the regular nvm inside your Linux environment instead of using nvm-windows.
Basic nvm Commands
Installing Node Versions
Install the latest version:
nvm install node
Install a specific version:
nvm install 18.17.0
Install the latest LTS (Long Term Support) version:
nvm install --lts
📌 Note: LTS versions are more stable and recommended for production projects. The latest version includes newer features but might have bugs.
Listing Installed Versions
See what you have installed:
nvm ls
This shows all installed versions and highlights which one is currently active. You'll see something like:
v16.20.0
v18.17.0
->v20.5.1
The arrow points to your current version.
Switching Between Versions
Use a specific version:
nvm use 18.17.0
Switch to the latest installed version:
nvm use node
Switch to the latest LTS:
nvm use --lts
Setting a Default Version
When you open a new terminal, nvm won't automatically select a version unless you set a default:
nvm alias default 18.17.0
Now every new terminal session will start with Node 18.17.0.
Uninstalling Versions
Remove a version you no longer need:
nvm uninstall 16.20.0
⚠️ Warning: You can't uninstall the version you're currently using. Switch to a different version first with
nvm use.
Practical Usage Patterns
Per-Project Node Versions
Instead of manually running nvm use every time you enter a project, create a .nvmrc file in your project root:
18.17.0
Then when you're in that directory, just run:
nvm use
nvm will read the .nvmrc file and switch to that version automatically. You can even add this to your shell profile to make it fully automatic (more on that later).
Working with Multiple Projects
Here's a real scenario: you're maintaining an older React app on Node 16 and building a new Next.js project on Node 20.
cd ~/projects/legacy-app
nvm use 16
cd ~/projects/new-nextjs-app
nvm use 20
Each terminal session maintains its own Node version, so you can have both projects open simultaneously in different terminal tabs.
Checking Which Version a Command Uses
Sometimes you need to verify which Node or npm version is actually running:
which node
# Output: /Users/yourname/.nvm/versions/node/v18.17.0/bin/node
node --version
# Output: v18.17.0
Common Gotchas and How to Avoid Them
Global npm Packages
When you install a global package with npm, it's tied to the Node version you're currently using. If you switch Node versions, those globals aren't available anymore.
nvm use 18
npm install -g typescript
nvm use 20
tsc --version # Command not found!
You'd need to reinstall TypeScript for Node 20. This is actually a feature, not a bug—it prevents version conflicts. But it can be surprising.
💡 Tip: Keep a list of your essential global packages somewhere. When you install a new Node version, you can quickly reinstall them.
npm vs npx
When using nvm, prefer npx over globally installed packages when possible. npx runs packages directly without installing them globally:
npx create-react-app my-app
This works regardless of your Node version and ensures you're using the latest package version.
Shell Integration
The default nvm setup requires you to manually run nvm use in each directory. You can automate this by adding a function to your shell config (~/.bashrc or ~/.zshrc):
# Automatically use .nvmrc version if present
autoload -U add-zsh-hook
load-nvmrc() {
if [[ -f .nvmrc && -r .nvmrc ]]; then
nvm use
fi
}
add-zsh-hook chpwd load-nvmrc
load-nvmrc
Now when you cd into a directory with a .nvmrc file, nvm switches versions automatically.
Troubleshooting Common Issues
"nvm: command not found"
This usually means the installation script didn't update your shell profile correctly. Manually add this to your ~/.bashrc or ~/.zshrc:
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
Then reload your shell:
source ~/.bashrc # or ~/.zshrc
Slow Shell Startup
nvm can make your shell start slower because it loads every time. If this bothers you, use lazy loading. Add this to your shell config instead:
export NVM_DIR="$HOME/.nvm"
nvm() {
unset -f nvm
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
nvm "$@"
}
This only loads nvm when you actually use it.
Permission Errors During Installation
If you see permission errors when installing Node versions, don't use sudo with nvm. The whole point is to avoid needing root access. If you're getting errors, it usually means nvm wasn't installed correctly. Reinstall it following the official instructions.
Quick Reference Table
| Command | What It Does |
|---|---|
nvm install 18.17.0 | Install specific Node version |
nvm install --lts | Install latest LTS version |
nvm use 18.17.0 | Switch to specific version |
nvm use --lts | Switch to latest LTS |
nvm ls | List installed versions |
nvm ls-remote | List all available versions |
nvm alias default 18.17.0 | Set default version |
nvm uninstall 16.20.0 | Remove a version |
nvm current | Show current version |
nvm which 18.17.0 | Show path to specific version |
When Not to Use nvm
nvm is great for development, but it's not ideal for production servers. In production, you typically want:
- A single, pinned Node version
- Faster startup times
- Docker containers or system package managers
For production deployments, use Docker with a specific Node base image, or install Node directly via your system's package manager and pin the version.
Alternatives Worth Knowing
- n: A simpler Node version manager with less features but faster performance
- fnm: Written in Rust, much faster than nvm, gaining popularity
- asdf: Can manage multiple languages (Node, Ruby, Python) with one tool
- volta: Made by the LinkedIn team, handles both Node and package managers
I still use nvm because it's well-established and works consistently, but fnm is worth checking out if startup speed matters to you.
Final Thoughts
nvm solves a real problem without being complicated. Once it's set up, you mostly forget it's there until you need to switch versions. That's the mark of a good tool.
The key things to remember:
- Always use
.nvmrcfiles in your projects - Set a sensible default version for new terminals
- Don't fight the per-version global packages design
- Keep your nvm updated occasionally with
nvm install node --reinstall-packages-from=node
That last command is particularly useful—it installs the latest Node version and migrates all your global packages from your current version.
If you're still manually downloading Node installers from the website and uninstalling versions by hand, give nvm a try. It takes five minutes to set up and saves you from a lot of future headaches.
