Skip to content

Which Package Manager Should a New Project Use in 2026?

pnpm, Yarn 4, npm 12 and Bun 1.4 timed cold and warm, measured on disk across three projects, and checked for what breaks. One pick for new projects.

· · 8 min read

Updated: October 3, 2026

A group of open cardboard boxes

Quick Take

Pnpm wins for a new project. Cold install 2.2s against npm's 4.45s, 232 MiB for three projects against npm's 607, and strict resolution by default. Bun is the fastest warm but the youngest. Yarn PnP failed my jsdom test run. npm stays the boring fallback.

Years ago npm cost me too much time and disk, so I moved to Yarn and stopped thinking about it. Then I started a new project, and that old decision was suddenly five years stale. So I re-ran the comparison: pnpm 12.8.1, npm 12.2.0, Yarn 4.18.1 (two linkers), Yarn Classic 1.22.22 and Bun 1.4.2, all against the same lockfile-pinned React 19 + Vite app, plus a 12-workspace monorepo.

How Was It Measured?

Everything ran on one Linux box (Xeon 2.1 GHz, 4 cores, 15 GB, ext4) with Node 22.23.3, each manager installed into its own isolated prefix with its own cache. Five runs per cell on the app, three on the monorepo, median shown with the range in brackets. Cold order was shuffled between repetitions so a network hiccup hit everyone. The harness, the fixtures and every raw run are in the repo under audits/coding-dunia/2026-10-03-package-manager-benchmark/.

The caveat that matters: the sandbox reached the npm registry in about 0.08s per tarball, which is much faster than a typical CI runner. Cold numbers here are therefore smaller than yours, and cold differences are mostly noise. Warm numbers, where nothing touches the network, are the trustworthy ones.

Seconds, single appnpm 12.2Yarn 1Yarn 4 nmYarn 4 PnPpnpm 12.8Bun 1.4
Cold, lockfile (frozen-cold)4.45 [4.34-5.98]14.6 [13.9-15.4]5.13 [5.00-6.13]3.77 [3.72-4.45]2.20 [2.17-4.20]3.48 [3.33-5.16]
Warm cache (frozen-warm)3.39 [3.07-3.53]3.28 [2.21-3.40]2.71 [2.62-3.00]1.37 [1.24-1.70]0.25 [0.14-0.41]0.086 [0.077-0.12]
Nothing changed0.540.281.000.960.0360.011
Add one package0.621.701.331.290.230.052

Read the cold row honestly. pnpm, Bun and Yarn PnP overlap, so call that a tie. npm sits clearly behind pnpm, Yarn 1 is clearly last. The monorepo told the same story: warm install 4.68s for npm, 0.39s for pnpm, 0.12s for Bun.

How Much Disk Do They Use?

One project barely separates them. Three projects sharing one cache separate them a lot, and that's the number the old benchmark of this article couldn't show.

MiB on disk (one du, hardlinks counted once)npmYarn 1Yarn 4 nmYarn 4 PnPpnpmBun
One project2171,084547424176221
Three projects, same cache6071,583969562232277

pnpm adds about 28 MiB per extra project because it links from one store. npm adds about 195. Bun does nearly as well as pnpm once the cache is shared, which surprised me. Yarn Classic keeps extracted copies of everything, and its cache alone was 888 MB. One warning on method: du counts hardlinked files once per invocation, so summing two separate du calls double-counts and made pnpm look twice as big (349 MiB) until I measured project and store together.

Stacks of grey and white shipping containers under a clear blue sky at a freight terminal
Photo by Marcus Reubenstein on Unsplash

What Actually Broke?

Speed is the number every landing page quotes. Breakage is the one that costs a day. Four things surfaced.

Yarn PnP failed my test run. vitest run with jsdom died with Failed to start forks worker, root cause ERR_VM_MODULE_LINK_FAILURE inside html-encoding-sniffer. Typecheck and build passed. I found no workaround, and Vite itself prints that PnP is discouraged.

Phantom dependencies split the field. I imported picocolors, which no package.json declares but a dependency pulls in. npm, Yarn 1, Yarn 4 node_modules and Bun resolved it happily. pnpm and Yarn PnP refused. Refusing is the right behavior, because that import works on your machine and dies the day the parent dependency drops it.

Dark silhouette of bare tree branches spreading in many directions against a pale sky
Photo by Joshua Bartell on Unsplash

Three managers blocked or changed my install by default. Yarn 4.18.1 refused to install a pinned @tanstack/react-query that had been published the previous day, because of its release-age gate. pnpm 12.8.1 has a similar gate and wrote its own exclusions into pnpm-workspace.yaml. On the monorepo, pnpm also failed with ERR_PNPM_IGNORED_BUILDS until I allowed esbuild's install script. Annoying for ten minutes, and defensible: both defaults exist to blunt supply-chain attacks.

npm refused a conflict the others waved through. latest TypeScript was 7.0.2, and typescript-eslint 8.71.0 wants <6.1.0. npm stopped with ERESOLVE. The other four installed with warnings. I'd call npm correct here.

The fastest package manager is the one whose defaults will not surprise you in year three, and a speed gap you can only measure warm is not worth trading a decade of track record for.

Share this Post on X Bluesky

Which Tool Has the Track Record?

You asked yourself the right question if you asked what happens in two years. Speed on day one is cheap to measure. Survival isn't. The registry gives hard dates for the first stable release:

ToolFirst 1.0 / 4.0 releaseVersions publishedNote
npmships with Node.js609the default everywhere
Yarn Classic1.0.0, Sep 2017120maintenance mode
pnpm1.0.0, Jun 20171,336major 12 now
Yarn 44.0.0, Oct 2023100PnP discouraged by Vite
Bun1.0.0, Sep 20231,343runtime plus package manager

pnpm and Yarn Classic are the same age, yet only one of them kept shipping. That, plus a store design that has not changed in nine years, is why I'm comfortable calling pnpm the pick. Bun's release cadence is impressive and its age is three years. If its install layout stays as inconsistent as I saw between single apps and workspaces, it's the one I'd re-check first. For what it's worth, the weekly download count of pnpm's own package was 236 million in the week to 1 October, against 11 million for Yarn Classic and 4.6 million for Bun, but CI runners inflate that number, so treat it as a direction, not a headcount.

What Is My Rule for Picking Tools?

I don't chase the new thing. A tool that looks better today often turns into a maintenance problem a year or two later, and then the project it was supposed to help quietly dies with it. So before I switch anything I ask one question: does this tool have a long enough history and wide enough use that it will still be fine in several years? If the answer is no, I'd rather stay on something imperfect that most people have used for a long time than jump to a newcomer and jump back. That rule is why Bun, for all its speed, isn't my pick, and why pnpm is: it passed the benchmark and the age test.

So Which One Should You Pick?

If you valuePick
Speed, disk and strictness together, long track recordpnpm
Zero extra tooling, smallest surprisenpm
Raw warm speed, willing to retest in a yearBun
An already-working Yarn 4 setup with node_modules linkerStay, no urgency
Yarn Classic or Yarn PnPPlan a move

My decision: pnpm. I moved the Yarn 4 monorepo behind this site to it, and the move is merged. Cold install went from 104.9s to 8.8s and disk from about 3.0 GiB to 1.65 GiB on my Linux box, with identical test and typecheck results. The migration guide covers what broke on the way. New projects get pnpm from day one. I'll update this article once the move has run on CI for a few weeks, because a benchmark is a prediction and a migrated repo is the evidence.

Set packageManager in package.json so everyone gets the same version. Pick pnpm for the dependency rules rather than the stopwatch. If a switch later turns out to be a mistake, the exit is cheap as long as the old lockfile stays in git history: in my tests a revert restored it byte for byte, while going back without it moved about 75 of 261 package versions. The step-by-step version of that move, including the rollback, is in the same guide.

One honest limit: these are one fixture on one machine on one day, so rerun the harness on yours. And the reasoning behind weighing exit cost over benchmark wins is in the exit cost criterion. I'll rerun this when pnpm 13 or Yarn 5 ships.

Frequently Asked Questions

Which package manager should I pick for a new project in 2026?
pnpm. On the same React 19 and Vite app it finished a cold frozen install in 2.2 seconds against 4.45 for npm 12.2, held three projects in 232 MiB where npm needed 607, and refused to resolve an undeclared dependency that npm, Yarn 1, Yarn 4 node_modules and Bun all let through. It also has the longest track record of the non-npm options: version 1.0.0 shipped in June 2017. If you want zero extra tooling and can live with a bigger disk bill, npm is the safe second choice.
Is Bun a good package manager if I don't use the Bun runtime?
It is the fastest tool here once the cache is warm, 0.09 seconds against 0.25 for pnpm, and its cold install tied pnpm inside the noise. What held me back is age and consistency, not speed. Bun 1.0.0 shipped in September 2023, and on my workspace fixture it switched to an isolated node_modules layout while the single app got the hoisted one, so its strictness depends on project shape. I would test it on a throwaway branch before trusting it for a project meant to live for years.
Does Yarn Plug'n'Play still work with common tooling?
Not cleanly in my test. A Vitest run with jsdom failed under PnP with ERR_VM_MODULE_LINK_FAILURE inside html-encoding-sniffer, while the same tests passed under every other setup. Tailwind also generated 5,983 bytes of CSS instead of 4,726 until I added a .gitignore for .yarn and .pnp files, and Vite prints that PnP is discouraged. Yarn 4 with the node_modules linker works fine, but then it has little advantage over npm.