Overview
Use pnpm for new projects and monorepos; use Yarn 4 (Berry) only when you want Plug’n’Play or Yarn constraints. As of 2026-10-01 pnpm is at 12.x (a Rust rewrite, stable since 12.0 on 2026-08-26) and Yarn Berry is at 4.18; the yarn package on npm is still Yarn Classic 1.22, which is in maintenance mode.
Comparison
| Dimension | pnpm 12 | Yarn 4 (Berry) |
|---|---|---|
| Layout | Content-addressable store, hard-linked strict node_modules | Plug’n’Play (.pnp.cjs, the default linker) or node-modules linker |
| Phantom dependencies | Blocked by the strict layout | Blocked by PnP; allowed with the node-modules linker |
| Workspaces | pnpm-workspace.yaml, catalog: version sharing | workspaces in package.json, constraints engine |
| Patching | pnpm patch | patch: protocol with diffs in the repo |
| Supply-chain controls | minimumReleaseAge (1 day by default since pnpm 11), blockExoticSubdeps, allowBuilds for install scripts | npmMinimalAgeGate (default one week), enableHardenedMode |
| Node requirement | Node 22 or newer (pnpm 11 raised the floor from 18) | Check the Yarn release you pin |
Pick pnpm when
Pick pnpm for most new work.
pnpm -r run buildruns a script in every workspace package in topological order.- Strict layout makes undeclared imports fail at install or build time instead of in production.
- Shared store saves disk and speeds cold installs across projects.
- Dependency install scripts run only for packages you list in
allowBuilds, and brand-new releases are held back for a day by default (pnpm 11). Tune both inpnpm-workspace.yaml. - pnpm 11 moved pnpm-specific settings out of
.npmrcintopnpm-workspace.yaml; keep only registry and auth settings in.npmrc.
# pnpm-workspace.yaml
packages:
- "apps/*"
- "packages/*"Pick Yarn when
Pick Yarn 4 when its distinct features carry the project.
- Plug’n’Play with zero-installs: no
node_modules, reproducible installs from.yarn/cache. Every dependency must be PnP-compatible; native or loosely written packages may needpackageExtensions. - Constraints: enforce workspace-wide rules (one version of React across packages) in the repo.
- An existing Yarn 4 workspace that works: stay.
- Yarn Classic (1.x) projects: move to Yarn 4 or pnpm. Do not stay on 1.x.
Migrate to pnpm
Import the lockfile, then fix phantom dependencies.
- Delete
node_modules; runpnpm importto buildpnpm-lock.yamlfrompackage-lock.jsonoryarn.lock, then remove the old lockfile. - Replace
npm runandyarncalls in scripts and CI; enable store caching in CI. - Declare every import in the right
package.json; undeclared ones now fail. - Pin the version in the
packageManagerfield so local runs and CI use the same pnpm.
See migrate-from-npm-to-pnpm for the full steps and turborepo-vs-nx for task caching on top of workspaces.
FAQ
Should I use pnpm or Yarn for a new project?
Use pnpm 12 by default for its strict node_modules layout, shared content-addressable store, and supply-chain controls. Use Yarn 4 only when you want Plug’n’Play with zero-installs or Yarn constraints.
Is Yarn Classic still supported?
Yarn Classic 1.22, still the yarn package on npm, is in maintenance mode. Move 1.x projects to Yarn 4 or pnpm.
What Node version does pnpm 12 need?
pnpm needs Node 22 or newer, since pnpm 11 raised the floor from 18. Pin the pnpm version in the packageManager field so local runs and CI match.
How do I migrate from Yarn or npm to pnpm?
Delete node_modules and run pnpm import to build pnpm-lock.yaml from package-lock.json or yarn.lock, then remove the old lockfile. Declare every import in the right package.json, because undeclared ones now fail.