Node.js ecosystem disk

npm vs Yarn vs pnpm: Which Package Manager Wastes the Least Disk Space?

If you have been writing JavaScript for more than a few months, your Mac has quietly accumulated gigabytes of package data you never asked to keep. The question of npm vs yarn vs pnpm disk space is not just academic — on a 256 GB MacBook Pro running macOS Sequoia or Tahoe, it can be the difference between a machine that breathes and one that crawls. This guide breaks down exactly where each package manager stores its data, how much space each approach typically consumes, and what you can safely delete right now.

Where Each Package Manager Stores Data on macOS

Before you can reclaim space, you need to know what you are looking for. Each tool scatters files across your home directory in slightly different ways.

npm

npm's global cache lives at ~/.npm. On a busy machine that has been running for a year or two, this directory routinely swells to 3–8 GB. It stores compressed tarballs of every package version you have ever installed, keyed by a content-addressed hash. npm also writes global packages to /usr/local/lib/node_modules (Intel) or, with a Homebrew-managed Node, to /opt/homebrew/lib/node_modules (Apple Silicon). Per-project dependencies land in ./node_modules inside each workspace.

Yarn Classic (v1)

Yarn v1 keeps its global cache at ~/.yarn/berry is not used here — the Classic cache path is ~/.yarn/cache and its global binary store is at ~/.yarn/bin. The cache typically mirrors npm in size because it also stores one compressed copy of each package tarball. Yarn v1's lock file (yarn.lock) is the only real differentiator at rest.

Yarn Berry (v2+)

Yarn Berry introduced Plug'n'Play (PnP) mode, which can eliminate node_modules entirely and store packages in a single zip archive inside .yarn/cache per project (or in a shared global cache at ~/.yarn/berry/cache). In PnP mode, the global cache is the authoritative copy and projects reference it directly, meaning installed packages are not duplicated. However, if you use nodeLinker: node-modules in .yarnrc.yml (common for compatibility), you are back to per-project node_modules folders.

pnpm

pnpm uses a content-addressable store at ~/.local/share/pnpm/store (the XDG-compliant default on macOS) and hard-links package files from that store into each project's node_modules. Because hard links share inodes on the same volume, you pay for each unique file exactly once — regardless of how many projects reference it. This is pnpm's headline advantage and the main reason it wins the disk-space comparison for most multi-project setups.

Disk Space Comparison: Real Numbers

The table below reflects typical measurements on an Apple Silicon Mac with a moderate JavaScript workload (10–20 projects, mostly React/Next.js or Node APIs). Your numbers will vary, but the relative ratios are consistent.

Package Manager Global Cache Location Typical Cache Size Per-Project node_modules De-duplication
npm v10 ~/.npm 3–8 GB Full copy per project None (each project isolated)
Yarn Classic v1 ~/.yarn/cache 2–6 GB Full copy per project None (each project isolated)
Yarn Berry v4 (PnP) ~/.yarn/berry/cache 1–4 GB None (PnP) or full copy (node-modules linker) Shared zip cache across projects
pnpm v9 ~/.local/share/pnpm/store 2–5 GB Hard-linked from store (near-zero extra space) File-level hard links — pay once per unique file

The critical insight: with npm or Yarn Classic, five projects that all depend on react@18 store five separate copies in their respective node_modules. With pnpm, all five share the same inodes on disk. On a laptop with 15 JavaScript projects, switching to pnpm has been reported to recover 20–40 GB compared to npm.

How to Check What Each Tool Is Actually Using

Open Terminal and run these commands to see your current footprint before touching anything.

  1. npm cache: du -sh ~/.npm
  2. Yarn Classic cache: du -sh ~/.yarn/cache
  3. Yarn Berry cache: du -sh ~/.yarn/berry/cache
  4. pnpm store: du -sh ~/.local/share/pnpm/store
  5. All node_modules across your projects (slow but thorough): find ~/Developer -name node_modules -type d -prune -exec du -sh {} + 2>/dev/null | sort -rh | head -30

That last command will surface the largest offenders. Cleaning up node_modules on Mac covers the deletion steps in detail, but read the next section first so you understand what is safe.

How to Clean Up Each Package Manager's Cache Safely

Each tool ships its own pruning command. Use these rather than deleting cache folders manually, because the tools can sometimes lock or write to cache mid-install.

Clean npm cache

  1. Verify first (reads only, safe): npm cache verify
  2. Purge everything: npm cache clean --force

After a clean, npm will re-download packages on the next install, so expect slower installs for a few days while the cache rebuilds.

Clean Yarn Classic cache

  1. List cached packages: yarn cache list
  2. Purge: yarn cache clean

Clean Yarn Berry cache

  1. Remove unused entries: yarn cache clean --mirror
  2. Or wipe entirely: rm -rf ~/.yarn/berry/cache (Berry will re-fetch on next yarn install)

Clean pnpm store

  1. Remove packages no longer referenced by any project on the machine: pnpm store prune
  2. This is the safest command — it only removes orphaned entries, not packages still hard-linked into active node_modules.

node_modules vs Cache: Two Different Problems

Many developers conflate the global cache with per-project node_modules, but they are separate disk consumers. The global cache lets installs skip the network; node_modules is the expanded, runnable tree your build tools actually read.

Deleting a project's node_modules is always safe if you still have the lock file — just run npm install (or the equivalent) to restore it. Deleting the global cache is also safe but will slow your next installs. What you should not delete is a pnpm store entry while a project's node_modules is hard-linked to it — that is exactly what pnpm store prune guards against.

If you want a broader picture of what is consuming space across all your development toolchains — not just Node, but Xcode DerivedData, Cargo build artifacts, Maven's ~/.m2/repository, and more — a tool like Crumb can audit all of these at once and show what is safe to delete before you remove anything.

pnpm's Hard-Link Store: the Technical Edge

pnpm's content-addressable store works by computing a hash of each file inside a package. When two projects require the same file at the same path with the same content, pnpm creates a hard link in both projects' node_modules pointing to the single file in ~/.local/share/pnpm/store. From macOS's perspective, the file has one inode and occupies disk space once, regardless of how many directory entries point to it.

There is an important caveat: hard links only work within a single APFS volume. If your pnpm store lives on an external drive or a different APFS volume than your projects, pnpm falls back to copying files, eliminating the space benefit. Most developers working from a single internal SSD will never hit this.

Which Should You Choose in 2026?

For a single developer with a handful of projects, the difference between npm and Yarn Classic is negligible — both will accumulate a few gigabytes of cache that you prune occasionally. The meaningful jump comes when you have many projects or work in a monorepo.

  • npm: Zero configuration, ships with Node, perfectly fine for 1–5 projects. Cache at ~/.npm is the main thing to watch.
  • Yarn Classic (v1): Faster installs than early npm versions, but now in maintenance mode. Not worth adopting new.
  • Yarn Berry (v4): PnP mode offers real de-duplication but requires ecosystem compatibility checks. Useful in monorepos with tight control over tooling.
  • pnpm: Best disk efficiency by default, no compatibility compromises, fastest install times in most benchmarks. Strongly recommended for anyone managing 5+ JavaScript projects on a Mac.

Whichever tool you use, the cumulative footprint of JavaScript development — caches, node_modules, build artifacts — tends to grow invisibly. Regular audits with du and the native cache-clean commands above, combined with periodic sweeps of orphaned node_modules folders, will keep your disk from filling up silently. For a full picture of what else is hiding in ~/Library/Caches and similar locations, see what is taking up space on your Mac.

Reclaim your disk in one click

Crumb audits your whole Mac, tells you what's safe to delete, and frees the space in seconds — private, local, and Apple-notarized.

Download Crumb for macOS

Frequently asked questions

Is it safe to delete the npm cache at ~/.npm?
Yes. The npm cache is a local copy of downloaded package tarballs used to speed up future installs. Deleting it (with 'npm cache clean --force' or by removing the folder) will not break any installed project. Your next 'npm install' will simply re-download the needed packages from the registry, which takes a bit longer than a cached install.
Where does pnpm store packages on macOS?
pnpm's content-addressable store lives at ~/.local/share/pnpm/store by default on macOS. You can check its path with 'pnpm store path'. Run 'pnpm store prune' to remove packages no longer referenced by any project on your machine without risking active installs.
Will switching from npm to pnpm break my existing projects?
Not usually. pnpm reads the same package.json and can generate a pnpm-lock.yaml from scratch. The main compatibility risk is code that relies on phantom dependencies — packages that are available in npm's hoisted node_modules but not declared in package.json. Run 'pnpm install' in a project and check for import errors; most codebases require no changes at all.
How much space can I realistically recover by cleaning up Node.js tooling?
On a Mac with several years of JavaScript development, 10–40 GB is common. The biggest contributors are accumulated node_modules folders from old or archived projects (which you can safely delete if you have the lock file), followed by the npm or Yarn global cache. Use 'du -sh ~/.npm ~/.yarn ~/.local/share/pnpm/store' to see your actual numbers.
Does Yarn Berry (PnP mode) really eliminate node_modules?
In PnP mode, yes — Yarn Berry replaces node_modules with a .pnp.cjs loader file and stores all package zips in .yarn/cache. However, many tools (Jest, some Babel configs, Electron) require a real node_modules tree, so teams often use the 'nodeLinker: node-modules' setting, which brings back per-project node_modules and negates most of the space benefit.