UseToolSuite UseToolSuite

npm vs Yarn: Which Node.js Package Manager Should You Use?

npm vs Yarn compared: install speed, lockfiles, workspaces, Plug'n'Play, and security — plus where pnpm fits. Which package manager to pick in 2026.

Necmeddin Cunedioglu Necmeddin Cunedioglu 4 min read
Part of the Core Web Vitals in 2026: The Complete INP, LCP, and CLS Optimization Playbook series

Practice what you learn

JSON Formatter & Validator

Try it free →

npm and Yarn both install the dependencies your Node.js project declares in package.json. They read your dependencies, resolve the full tree (including dependencies of dependencies), download the packages, and write a lockfile so everyone gets the exact same versions.

The differences are smaller than they used to be. Yarn arrived in 2016 to fix real npm problems of the time — slow installs and no lockfile — and npm has since adopted both ideas. Today the choice is mostly about workflow features and team preference.

1. A Quick History

When Yarn launched, npm had two big weaknesses: installs were slow, and there was no lockfile, so two developers running npm install could end up with different dependency versions. Yarn fixed both — it was much faster and introduced yarn.lock for deterministic installs.

npm responded. npm 5 (2017) added package-lock.json and a local cache, and later versions kept improving install speed. The gap that made Yarn essential largely closed.

Meanwhile Yarn itself split into two products:

  • Yarn Classic (v1): the original, now in maintenance mode.
  • Yarn Berry (v2+): a rewrite with Plug’n’Play, an offline cache, and a plugin system. It behaves quite differently from Classic.

And pnpm emerged as a third option that many teams now prefer.

2. Lockfiles

Both tools write a lockfile that pins the exact version of every package in the tree, so installs are reproducible.

  • npm writes package-lock.json.
  • Yarn writes yarn.lock.

The important rule: commit your lockfile, and use one package manager per project. If you have both package-lock.json and yarn.lock, different developers (and CI) can resolve different dependency trees, which causes bugs that only appear on some machines.

For reproducible CI installs, use the lockfile-strict commands:

  • npm ci — installs exactly what’s in package-lock.json, failing if package.json and the lockfile disagree.
  • yarn install --immutable — the Yarn Berry equivalent.

3. Command Comparison

The day-to-day commands map closely:

TasknpmYarn
Install all dependenciesnpm installyarn
Add a packagenpm install lodashyarn add lodash
Add a dev dependencynpm install -D vitestyarn add -D vitest
Remove a packagenpm uninstall lodashyarn remove lodash
Run a scriptnpm run buildyarn build
Reproducible CI installnpm ciyarn install --immutable

4. Workspaces (Monorepos)

Both support workspaces — managing multiple packages in one repository with a single install and shared dependencies. This is the main reason teams reach for Yarn or pnpm over plain npm, though npm has supported workspaces since v7.

// package.json at the repo root
{
  "workspaces": ["packages/*", "apps/*"]
}

For large monorepos, Yarn Berry and pnpm have more mature workspace tooling (better hoisting control, filtering commands to specific packages), which is why they’re common in that setting.

5. Yarn Berry’s Plug’n’Play

Yarn Berry’s headline feature is Plug’n’Play (PnP), which eliminates the node_modules folder entirely. Instead of unpacking thousands of files into a deeply nested directory, Yarn keeps packages as zip files and uses a single map file to tell Node where to find each one.

The upside: faster installs and no giant node_modules. The downside: some tools and packages assume node_modules exists, so PnP can require configuration or patches. That friction is why many teams stayed on Yarn Classic or moved to pnpm instead.

6. The pnpm Alternative

pnpm deserves a mention because it’s now a common default. It stores one copy of each package version in a global content-addressable store and hard-links it into each project’s node_modules. The benefits:

  • Disk space: ten projects using the same version of a package share one copy on disk instead of ten.
  • Speed: linking is faster than copying.
  • Correctness: pnpm’s node_modules is non-flat, so you can only import packages you actually declared. With npm and Yarn’s flat layout, you can accidentally import a “phantom dependency” — a package that’s only present because something else depends on it — which breaks the day that transitive dependency changes.

7. Security

All three run install scripts and pull code from the registry, so the security practices are the same regardless of which you pick:

  • Commit the lockfile and use the strict install command in CI (npm ci, yarn install --immutable, pnpm install --frozen-lockfile).
  • Run npm audit (or the Yarn/pnpm equivalent) to check for known vulnerabilities.
  • Be cautious with packages’ post-install scripts — they run arbitrary code. Recent npm and pnpm versions let you restrict which dependencies’ install scripts are allowed to run.

8. Which to Choose

  • npm: the default. It ships with Node, needs no extra install, and is fine for most projects. Choose it unless you have a specific reason not to.
  • Yarn Berry: worth it if you want PnP’s strictness or you’re already invested in the Yarn ecosystem and its plugins.
  • pnpm: the best pick for monorepos and for teams that want fast installs, disk savings, and protection against phantom dependencies. It’s the option that’s gaining the most ground.

Whichever you choose, the only firm rule is to standardize on one per project, commit the lockfile, and use the strict install command in CI. That’s what actually prevents dependency bugs — far more than the choice of tool.

Necmeddin Cunedioglu
Necmeddin Cunedioglu Author
4 min read
-- views

Software developer and the creator of UseToolSuite. I write about the tools and techniques I use daily as a developer — practical guides based on real experience, not theory.