What Is pnpm? The Faster npm Alternative, Explained
pnpm is a JavaScript package manager built to save disk space and speed up installs versus npm and Yarn. Here is how its shared store and stricter node_modules structure work.

Quick answer: pnpm is a JavaScript package manager built as a faster, more disk-space-efficient drop-in replacement for npm. Instead of copying a fresh set of dependency files into every project, pnpm keeps one shared store on disk and hard-links files into each project's node_modules, and it enforces a stricter folder structure that stops code from silently importing packages it never declared.
pnpm — short for "performant npm" — is an open-source package manager for JavaScript and Node.js projects, designed as a direct alternative to npm and Yarn that targets two specific problems: wasted disk space from duplicated dependencies, and the ability for code to quietly depend on packages a project never actually listed. It has become one of the more commonly adopted alternatives to npm's default client, particularly among teams managing several related JavaScript projects at once.
What Is pnpm?
According to pnpm's own documentation, it is a package manager that functions as "a drop-in replacement for npm" while adding features aimed at large codebases and monorepos. Like npm and Yarn, pnpm reads a project's package.json, resolves and downloads its dependencies, and installs them into a node_modules folder so Node.js can find them — the commands (pnpm install, pnpm add, pnpm run) are deliberately close to npm's own, so switching doesn't require relearning a workflow.
Where pnpm differs is entirely in how it stores and links those files on disk, which is also where its name and its two headline claims — speed and space savings — come from.
The Problem pnpm Solves
pnpm's own documentation frames the issue plainly: "Other package managers copy the same files into every project," so if ten projects on a machine all depend on the same version of a library, that library's files get physically duplicated ten times on disk. For a large dependency tree repeated across many projects — common in both individual developer machines and CI systems that check out fresh copies repeatedly — that adds up to a meaningful amount of wasted space and install time.
How pnpm's Storage Model Works
pnpm's docs describe a content-addressable store: every version of every package is downloaded and kept exactly once, in one global location on disk, identified by the content of its files rather than its name and version number alone. When a project needs that package, pnpm doesn't copy the files — it hard-links them from the store into the project's node_modules, so installed copies take no additional disk space beyond the one original.
The docs give a concrete illustration of why this also speeds up updates: for a package with 100 files where a new version changes just one of them, running pnpm update only needs to add that single changed file to the store — the other 99 are already there, shared with the previous version. pnpm's documentation also notes that sharing same-version dependencies across many projects saves disk space in rough proportion to how many projects and shared dependencies are involved — the more overlap, the bigger the savings.
Why pnpm Is Faster
pnpm's documentation describes installs happening in three stages, run with more parallelism than the traditional approach of resolving, downloading and writing everything sequentially into node_modules:
- Resolve the dependency tree and fetch any packages not already in the local store.
- Calculate the
node_modulesdirectory structure that the project needs. - Link the already-downloaded files from the store into the project via hard links.
Because step 3 is a hard link rather than a file copy, and step 1 often has little or nothing left to actually download on a second project using the same dependencies, pnpm's own published benchmarks claim installs up to 69 times faster than npm in some scenarios, and 8.2 times faster in total across the six scenarios the benchmark covers — figures pnpm attributes to running resolution, fetching and linking in parallel rather than one after another.
pnpm vs. npm vs. Yarn
| npm | Yarn (Classic) | pnpm | |
|---|---|---|---|
| Storage model | Copies files into each project's node_modules | Copies files into each project's node_modules | One shared content-addressable store, hard-linked per project |
| Disk usage across many projects | Duplicated per project | Duplicated per project | Shared — one copy on disk regardless of project count |
| node_modules structure | Flat (hoisted) | Flat (hoisted) | Non-flat by default — only declared dependencies are visible at the root |
| Can import undeclared ("phantom") dependencies | Yes, if hoisted by another package | Yes, if hoisted by another package | No, by default |
| Drop-in CLI compatibility with npm | — | Partial | Yes, per pnpm's own documentation |
Phantom Dependencies and Why pnpm's Structure Matters
npm and Yarn Classic both "hoist" dependencies, flattening the entire dependency tree into the top level of node_modules for compatibility and simplicity. The side effect is that a project's source code can successfully import a package it never listed in its own package.json, as long as some other dependency happens to pull that package in too — code that works today purely by accident, and can break the moment the dependency that was hoisting it gets removed or updated.
pnpm's non-flat structure avoids this by default: pnpm's docs explain that only a project's own, directly declared dependencies are symlinked into the root of node_modules, while the full resolved dependency tree lives in a nested node_modules/.pnpm folder instead. Code that tries to import something it didn't declare simply won't find it — the import fails immediately during development, rather than working by coincidence until a later dependency update quietly removes the package that happened to be hoisting it in. For projects or tools that don't handle this symlinked structure well, pnpm's docs note a nodeLinker setting can be switched to hoisted to fall back to an npm/Yarn Classic-style flat layout.
pnpm vs. Bun and Deno
pnpm is sometimes mentioned alongside newer, all-in-one JavaScript runtimes like Bun and Deno, both of which also ship their own fast, built-in package installers as part of the runtime itself — but the two solve different layers of the same problem. Bun and Deno are full runtimes — alternatives to Node.js itself, with their own built-in package managers. pnpm, by contrast, is only a package manager: it still installs packages for, and runs scripts through, the existing Node.js runtime (or Bun's or Deno's compatibility layers, where supported), rather than replacing the JavaScript engine underneath a project. A team can adopt pnpm without touching which runtime actually executes their code, which is one reason it's seen comparatively low-friction adoption even at companies that haven't changed anything else about their JavaScript tooling.
pnpm for Monorepos
Beyond single projects, pnpm's documentation highlights built-in support for workspaces — multiple packages living in one repository, which is increasingly how larger JavaScript codebases are organized. Per pnpm's own feature list, this includes installing all workspace packages with a single lockfile, filtering commands to run only against packages that actually changed, and "catalogs," a way to centralize a dependency's version number in one place so every package in the workspace references the same version instead of drifting apart one package at a time.
This matters more as a codebase grows: in a large monorepo with dozens of internal packages that all depend on, say, the same version of a shared utility library, npm or Yarn Classic would ordinarily duplicate that library's files into every one of those packages' own node_modules. Under pnpm's store model, that same library exists once on disk regardless of how many internal packages reference it, and a workspace-wide pnpm install only needs to resolve and link, not re-download, anything already in the shared store from building a sibling package moments earlier.
pnpm and Node.js Version Management
Because a package manager and the underlying JavaScript runtime are separate pieces of tooling, pnpm's own documentation notes it can also manage which Node.js version a given project uses, letting different projects on the same machine pin different Node.js versions without a separate version-manager tool. That's a convenience layered on top of pnpm's core job — resolving and installing packages — rather than a replacement for Node.js itself, the same way pnpm doesn't replace npm's public package registry, only the client that talks to it.
Is pnpm Compatible With Existing npm Packages?
Yes, in the overwhelming majority of cases. pnpm installs from the same public npm registry as npm and Yarn, so the packages themselves are identical — what differs is only how they're laid out on disk afterward. The main category of compatibility issue pnpm's documentation acknowledges is tooling or scripts that assume the old flat, hoisted node_modules structure and break when a dependency they weren't supposed to rely on directly (a phantom dependency) is no longer reachable. pnpm's own guidance for this is the nodeLinker: hoisted setting mentioned above, which trades away pnpm's stricter default layout for maximum compatibility with tools that haven't been updated to expect it. In practice, this mostly affects older or unusually structured projects rather than typical modern JavaScript codebases.
pnpm also restricts which installed packages are allowed to run build scripts (like Node native-module compilation) by default, requiring explicit approval — a safeguard against a compromised or malicious package silently running arbitrary code during install, a real-world supply-chain risk that has affected the npm ecosystem more than once.
How to Install and Use pnpm
- Install pnpm — pnpm's official site offers several install methods, including a standalone script, Corepack (Node.js's built-in package-manager manager), and installing via npm itself.
- Run
pnpm installin a project with an existingpackage.json, the same way you would with npm. - Use familiar commands —
pnpm add <package>,pnpm remove <package>andpnpm run <script>all mirror npm's own command names. - For a monorepo, add a
pnpm-workspace.yamlfile listing the workspace's packages to enable cross-package commands and a shared lockfile. - Switching from npm or Yarn — running
pnpm importconverts an existingpackage-lock.jsonoryarn.lockfile into pnpm's own lockfile format, so a project can move over without re-resolving its entire dependency tree from scratch.
What's Next
pnpm's pitch is narrow and specific: keep npm's familiar commands and ecosystem compatibility, but fix the duplication and hoisting problems that come from how npm and Yarn Classic historically laid out node_modules. For a single small project the difference may be modest; for a developer machine or CI system juggling many projects that share dependencies, or a monorepo with many internal packages, pnpm's store-and-hard-link model is where most of its claimed speed and disk savings actually show up.
Switching an existing project over is typically low-risk to try: because pnpm reads the same package.json and installs from the same npm registry, testing it on a project usually means running pnpm import to convert an existing npm or Yarn lockfile, then pnpm install, and seeing whether anything in the build or test suite breaks under the stricter, non-flat node_modules layout before committing to the switch team-wide.
Frequently asked questions
What does pnpm stand for?
pnpm stands for 'performant npm.' It's a package manager for JavaScript and Node.js projects designed as a faster, more disk-space-efficient drop-in replacement for npm.
Is pnpm faster than npm?
pnpm's own published benchmarks claim installs up to 69 times faster than npm in some scenarios, and 8.2 times faster in total across the six scenarios tested, attributed to running dependency resolution, fetching and linking in parallel and hard-linking files instead of copying them.
How does pnpm save disk space?
pnpm keeps one content-addressable store on disk holding every package version exactly once, then hard-links those files into each project's node_modules instead of copying them, so installed copies take no additional disk space beyond the original.
What are phantom dependencies?
A phantom dependency is a package a project's code can successfully import even though it was never listed in that project's own package.json, because npm or Yarn Classic hoisted it to the top of node_modules from some other dependency. pnpm's non-flat node_modules structure prevents this by default.
Is pnpm compatible with npm packages?
Yes. pnpm installs from the same public npm registry as npm and Yarn, so packages themselves are identical. Compatibility issues are rare and mostly involve tooling that assumes the old flat node_modules layout, which pnpm's hoisted nodeLinker setting can restore if needed.
Does pnpm support monorepos?
Yes. pnpm has built-in workspace support for installing multiple related packages with a single lockfile, filtering commands to only changed packages, and catalogs for centralizing a dependency's version across an entire workspace.
Sources
- pnpm.io — official pnpm sitepnpm.io
- pnpm Docs — Motivationpnpm.io
- pnpm Docs — Installationpnpm.io
- pnpm Docs — Workspacepnpm.io
Felix Moreau writes Pandromeda's software coverage and how-to guides. He covers Windows, macOS and Linux updates, the apps people rely on, emulators and developer tools, and turns official documentation into clear, numbered steps that work on the current version.


