deniz.in

Markets

Weather

Loading weather

· via dev.to (home feed)

pnpm's disk savings shine in monorepos; npm stays the simpler pick for small projects

A dev.to comparison finds pnpm's shared content-addressable store cuts real duplication in monorepos and cached CI, while single-package projects gain little and inherit migration friction.

pnpm's disk savings shine in monorepos; npm stays the simpler pick for small projects

A comparison published on dev.to by jtorchia argues that the npm-versus-pnpm question is decided less by speed benchmarks than by the shape of your repository: pnpm's shared store delivers measurable savings in monorepos and cached CI pipelines, while npm remains the pragmatic default for small, single-package projects.

What each package manager puts on disk

According to the post, npm writes a physical copy of every dependency into node_modules. In a workspace where four packages all declare the same version of lodash, that copy can exist in several places in the tree unless you rely on aggressive hoisting — a tactic the author notes brings its own phantom-dependency problems.

pnpm, per its own motivation documentation cited in the post, takes a different architectural route: each package version is downloaded once into a global content-addressable store located outside the project, and the node_modules directories inside a repo hold symlinks pointing into that store. If ten projects on one machine use the same library version, that version exists exactly once on disk.

The author's central point follows from that model: savings scale with the number of packages in the workspace that share dependencies, not with the total dependency count. A lone package. with ten production dependencies gives the symlink model nothing to deduplicate.

Install time is more conditional. If a package already sits in the local store, pnpm can skip downloading it; on a CI runner with a cold cache, the first download weighs the same under either manager. Disk savings are consistent — time savings are not.

Where migration friction hides

The post describes a familiar sequence: a small Next.js project is migrated after someone reads a thread praising pnpm, and the cost surfaces later, outside the project itself. CI scripts, Docker images that run npm ci, and dependency linters that parse package-lock. have no idea what to do with pnpm-lock.yaml.

Strictness adds to the bill. pnpm rejects undeclared dependencies that npm's hoisting quietly made reachable, so scripts that leaned on those phantom packages can start failing with ERR_PNPM_NO_MATCHING_VERSION. Team members also need to learn .pnpmfile.cjs and how to debug a symlink-based layout.

A decision matrix

The author sketches several scenarios:

  • Monorepos with three or more packages sharing dependencies: real savings; check how many dependencies overlap between packages.
  • CI with dependency caching between runs: worthwhile, provided the runner can cache the global store and not just the lockfile.
  • A single project without workspaces: marginal gains; weigh whether the team already knows pnpm or needs training.
  • Multistage Docker builds: depends — the Dockerfile has to be adjusted to copy the store, and the image-size savings may or may not justify the change.
  • Teams with npm-specific scripts in a mature CI/CD setup: not worth it unless those scripts are rewritten.

The matrix is a starting point, the author cautions, not a substitute for measuring on your own project.

Workspaces and the deeper difference

npm has supported workspaces since v7, hoisting dependencies toward the monorepo root. It works, the post concedes, but it does not deduplicate between different monorepos on the same machine — each repo re-downloads and stores its own physical copy. pnpm's workspace:* protocol, by contrast, symlinks sibling packages directly without going through the registry.

The author frames the gap as architectural rather than a missing feature: the two managers disagree about where the bytes live.

What the comparison cannot tell you

The post is explicit about its limits: it offers no original install-time benchmark. From the storage model you can deduce that deduplication scales with workspace size, but you cannot conclude how much time pnpm saves on a given CI run — that depends on the runner, cache size and network — or whether disk savings justify rewriting Docker configuration and lockfile-dependent tooling. Native dependencies that compile different binaries per symlink are flagged as a case where pnpm can add friction, one the post does not cover.

The honest way to a number for a team decision, the author writes, is to run both installers on the same project with the same cold cache and measure it yourself.

Why it matters

Package manager choice is often argued as taste or chased as hype. This comparison reframes it as an architectural decision whose costs appear outside the install command — in CI scripts, Docker recipes and linters that silently assumed npm's behavior. For monorepo teams, pnpm's content-addressable store attacks a duplication problem that grows with every workspace package; for a single-package app, the same machinery adds a learning curve with little to optimize. Knowing which situation you are in, and measuring before migrating, is the actual takeaway.

  • #pnpm
  • #npm
  • #node-js
  • #package-managers
  • #monorepos