TL;DR: npm is not bad, but it was designed fifteen years ago, when projects had five dependencies and nobody worried about disk duplication. Today, two competitors (pnpm and bun) do the same work faster, with less disk space, and with safer behavior. You have almost no reason to choose npm for a new project in 2026.
The historical problem with npm
When you run npm install in a project:
- npm downloads each dependency once per project, into
node_modules/. - Each sub-dependency is also downloaded and copied, sometimes multiple times if it is referenced by different packages at slightly different versions.
- On your disk, an average-sized project weighs 300 MB to 1 GB in
node_modules/. If you have ten projects, that is ten times the volume.
Concrete consequence: a node_modules/ folder that takes five minutes to install, several gigabytes on your SSD, and is generally heavier than the rest of the project put together.
The second problem: permissive resolution
By default, npm "flattens" dependencies. Package A that depends on B can, as a side effect, access any package C that another package installed, even if your project does not explicitly depend on C. This is called the phantom dependency problem.
Consequence: your code works locally, then one day a package update removes the phantom dependency, and your build breaks in production without you having touched your code. Painful to diagnose, annoying to reproduce.
The third problem: speed
npm executes many tasks serially. On a project with 100 dependencies, the initial install easily takes 30 to 60 seconds, sometimes much longer on a slow connection. On a CI that reinstalls everything on each build, that is real time and wasted carbon.
What pnpm and bun do instead
- pnpm keeps a single copy of each package in a global store (
~/.local/share/pnpm/storeor equivalent), then creates hardlinks innode_modules/. On disk, a single physical file serves ten projects. - bun goes further: a binary written in Zig, aggressive parallelization, 5 to 20 times faster installs than npm on public benchmarks.
- Both enforce strict resolution by default: a package can only access its declared dependencies. Phantom dependency bugs become impossible.
When to keep npm
- Existing project already on npm, with a team that knows it and a
package-lock.jsonthat works. No urgency to migrate. - Very constrained environment: some very old hosting providers only support npm. Increasingly rare in 2026.
- Compatibility with a third-party tool that makes assumptions about the
node_modules/structure. Also rare.
Outside these cases, no reason to choose npm for a new project. The next lesson breaks down the differences between pnpm and bun so you can make an informed choice between the two.