|$ curl https://forge-ai.dev/api/markdown?path=docs/npm/compare
$cat docs/npm-vs-yarn-vs-pnpm-vs-bun.md
updated Today·22-30 min read·published

npm vs Yarn vs pnpm vs Bun

npmYarnpnpmBunIntermediate🎯Free Tools
Introduction

Four package managers dominate the JavaScript ecosystem: npm (ships with Node), Yarn (Classic and Berry), pnpm (strict, content-addressable), and Bun (runtime + installer). They all read package.json, talk to the npm registry, and produce a lockfile — but they differ in how they lay out node_modules, how they cache packages, and how well they scale monorepos.

This page is the decision matrix. Deep dives live under Yarn, pnpm, Bun, and Corepack.

📝

note

Pick one manager per repo and pin it with packageManager+ Corepack (or an equivalent CI install). Mixing lockfiles is a common source of "works on my machine" bugs.
At a Glance
DimensionnpmYarn BerrypnpmBun
Default with NodeYesNo (Corepack)No (Corepack)Separate install
Lockfilepackage-lock.jsonyarn.lockpnpm-lock.yamlbun.lock / bun.lockb
LayoutHoisted treePnP or node_modulesIsolated + storeHoisted (npm-like)
Best atDefault / tutorialsZero-Installs, constraintsMonorepos, diskSpeed + runtime
Install Speed

Numbers below are order-of-magnitude for a mid-size Next.js app (~800–1200 packages) on a warm network. Absolute times vary; relative ranking is stable across public benchmarks.

ScenarionpmYarn Berry (PnP)pnpmBun
Cold install (empty cache)Baseline (slowest)FastFastFastest
Warm cache, clean node_modulesModerateVery fast (or Zero-Install)Very fast (hard links)Very fast
CI with lockfile + cache hitGood with npm cacheExcellent / skip installExcellentExcellent
Add one dependencyOKFastFastFastest
benchmark-hints.sh
Bash
1# Rough local timing (same machine, same lockfile generation strategy)
2time npm ci
3time yarn install --immutable
4time pnpm install --frozen-lockfile
5time bun install --frozen-lockfile
6
7# Clear only project modules between runs; keep global caches to measure warm path
8rm -rf node_modules

info

Optimize for ci / frozen lockfile installs, not interactive install without a lock. That is the path CI and production images take.
Disk Use

Disk cost has two parts: per-project node_modules (or PnP cache) and the global store/cache shared across projects.

ManagerPer-project footprintGlobal storeNotes
npmFull copies (hoisted tree)~/.npm cache (tarballs)Many projects = many copies
Yarn ClassicSimilar to npmYarn cacheLegacy; prefer Berry or pnpm
Yarn Berry PnPZip cache + .pnp.cjsOptional global cacheZero-Installs commit cache
pnpmSymlinks + hard linksContent-addressable storeBest multi-project disk savings
Bunnpm-like tree (optimized)Bun global cacheFast; not as thrifty as pnpm store
🔥

pro tip

On a laptop with ten Node monorepos, pnpm's hard-linked store often saves gigabytes versus npm. That is the main reason large orgs standardize on pnpm.
Lockfile Names & Formats
ManagerLockfileHuman-readableCommit?
npmpackage-lock.jsonYes (JSON)Always
Yarnyarn.lockYesAlways
pnpmpnpm-lock.yamlYes (YAML)Always
Bunbun.lock (text) or bun.lockb (binary)Text preferredAlways
gitignore-hygiene.sh
Bash
1# Commit the lockfile that matches your chosen manager — only one
2# Do NOT commit multiple lockfiles from competing managers
3
4# Ignore install artifacts
5echo 'node_modules/' >> .gitignore
6# Yarn Berry: usually commit .yarn/releases and often .yarn/cache (Zero-Installs)
7# pnpm: commit pnpm-lock.yaml; do not commit the global store

warning

Having both package-lock.json and pnpm-lock.yaml in the same repo means different developers may install different trees. Delete the unused lockfile and document the canonical manager in README + packageManager.
node_modules Strategy

How packages appear on disk controls phantom dependencies, peer resolution, and tool compatibility.

StrategyUsed byPhantom depsTooling compatibility
Hoisted flat-ish treenpm, Yarn Classic, Bun, Yarn node-modulesEasy to accidentally importHighest
Isolated + symlinkspnpm (default)Blocked (good)High; rare packages need shamefully-hoist
Plug'n'PlayYarn Berry defaultBlockedNeeds SDKs; some packages break
.yarnrc.yml
YAML
1# Yarn Berry: fall back to classic layout when PnP breaks a tool
2nodeLinker: node-modules
.npmrc (pnpm)
INI
1# Escape hatch when a tool expects hoisted packages
2shamefully-hoist=true
3# Or hoist only patterns:
4# public-hoist-pattern[]=*eslint*
5# public-hoist-pattern[]=*prettier*
Monorepo Support
FeaturenpmYarn BerrypnpmBun
WorkspacesYesYes (mature)Yes (mature)Yes
Filter / foreachBasic -wworkspaces foreach--filter (best)--filter
Catalogs / shared versionsNoConstraintscatalogsLimited
Strict peersWarningsConfigurableStrict by defaultnpm-like
Typical choice at scaleSmall reposTeams on PnP/Zero-InstallMost monoreposSpeed-first apps
monorepo-commands.sh
Bash
1# npm
2npm run build -w @acme/web
3npm run test --workspaces --if-present
4
5# Yarn Berry
6yarn workspaces foreach -A run build
7yarn workspace @acme/web add zod
8
9# pnpm
10pnpm --filter @acme/web build
11pnpm --filter "./packages/**" test
12
13# Bun
14bun run --filter @acme/web build
When to Choose Each
ChooseWhenAvoid when
npmTutorials, OSS default, zero extra tooling, simple appsLarge monorepos needing strict isolation
Yarn BerryWant PnP, Zero-Installs, constraints pluginsTeam unwilling to adopt PnP SDKs / plugins
pnpmMonorepos, disk savings, strict deps, catalogsTools that hard-require npm flatten (rare; hoist escapes exist)
BunNeed max install + runtime speed; greenfieldNeed maximum Node API parity / conservative ops

best practice

For most new company monorepos in 2025–2026, start with pnpm + Corepack. Use npm for single-package libs that must match contributor defaults. Evaluate Bun when the whole stack (test runner, bundler, runtime) can move together.
Migration Notes

Migrate one repo at a time. Keep CI green on the old manager until the new lockfile is committed and scripts verified.

migrate.sh
Bash
1# npm → pnpm
2pnpm import # reads package-lock.json
3rm package-lock.json
4pnpm install
5# set "packageManager": "pnpm@9.x.x" in package.json
6# enable Corepack in CI
7
8# npm → Yarn Berry
9corepack enable
10yarn set version stable
11yarn install
12rm package-lock.json
13# if PnP breaks tools: yarn config set nodeLinker node-modules
14
15# npm → Bun
16bun install # generates bun.lock
17rm package-lock.json
18# verify: bun run test && bun run build
19
20# Any → npm
21# delete other lockfiles, npm install, commit package-lock.json
Watch forWhyFix
Phantom importspnpm/PnP stop undeclared requiresAdd real dependency or use packageExtensions
postinstall scriptsSecurity / Bun settings differAudit trustedDependencies / ignore-scripts
patched packagespatch-package vs pnpm patch vs yarn patchRe-apply with native patch tool
engines / only-allowBlock wrong managerUpdate preinstall hook after switch
Corepack

Corepack ships with Node and can download/pin Yarn and pnpm versions from the packageManager field. Bun is not managed by Corepack — install Bun separately.

package.json
JSON
1{
2 "name": "acme",
3 "private": true,
4 "packageManager": "pnpm@9.15.0"
5}
corepack.sh
Bash
1corepack enable
2corepack prepare pnpm@9.15.0 --activate
3# CI: enable once on the runner image, then pnpm install --frozen-lockfile

Full guide: Corepack.

Command Cheat Sheet
TasknpmYarnpnpmBun
Installnpm installyarnpnpm installbun install
CI frozennpm ciyarn --immutablepnpm i --frozen-lockfilebun i --frozen-lockfile
Add depnpm i lodashyarn add lodashpnpm add lodashbun add lodash
Dev depnpm i -D vitestyarn add -D vitestpnpm add -D vitestbun add -d vitest
Run scriptnpm run buildyarn buildpnpm buildbun run build
One-off binarynpx eslint .yarn dlx eslint .pnpm dlx eslint .bunx eslint .
Updatenpm updateyarn uppnpm upbun update
Decision Flow
  1. Need maximum ecosystem conservatism and contributor familiarity? → npm.
  2. Multi-package monorepo, disk/CI efficiency, strict deps? → pnpm.
  3. Want committed dependency zips and no CI install? → Yarn Berry Zero-Installs.
  4. Optimizing for install + JS runtime speed and can accept Bun caveats? → bun.
  5. Pin the choice with packageManager / Corepack (or Bun version in CI image).
📝

Community

Get help on Slack, Discord or VIP

Stuck on a guide? Join the community and ask.