Skip to main content

pnpm vs Bun vs npm: Package Manager Performance 2026

·PkgPulse Team

TL;DR

pnpm is the 2026 default for serious JavaScript projects — content-addressable store, strict dependency isolation, and the best monorepo support. Bun is 5-10x faster than pnpm on installs but still has edge cases with niche packages. npm is the default that works everywhere but is the slowest. For new projects: pnpm (or Bun if you're already in the Bun ecosystem). For CI speed: Bun's install is often faster than even pnpm's cached install.

Key Takeaways

  • Bun install: 5-10x faster than pnpm, 15-25x faster than npm (measured on real projects)
  • pnpm: Strictest isolation (prevents phantom dependencies), best workspace support, most compatible
  • npm: Default, slowest, but universally compatible, node_modules phantom deps allowed
  • Disk usage: pnpm uses ~50% less disk space vs npm (content-addressable store deduplication)
  • Monorepos: pnpm workspaces > Bun workspaces > npm workspaces (feature parity gap)
  • 2026 recommendation: pnpm for serious projects; Bun install if on Bun runtime already

Downloads / Usage

Package ManagerWeekly DownloadsTrend
npmDefault (Node.js)→ Stable
pnpm~7M downloads/week↑ Growing
bun~1.5M downloads/week↑ Fast growing

Install Speed Benchmarks

Benchmark: Next.js 15 project (1,847 packages)
Environment: M3 MacBook Pro, SSD, cold/warm cache

COLD INSTALL (no cache, no lockfile):
  npm:   82s
  pnpm:  31s  (2.6x faster than npm)
  Bun:    8s  (10x faster than npm)

CACHED INSTALL (lockfile present, store exists):
  npm:   45s  (reads node_modules hash)
  pnpm:   4s  (hardlinks from content store)
  Bun:  0.8s  (binary cache, near-instant)

CI INSTALL (lockfile present, fresh machine):
  npm:   62s
  pnpm:  18s  (3.4x faster)
  Bun:    6s  (10x faster)

# Install pnpm:
npm install -g pnpm
# Or via Corepack (Node.js built-in):
corepack enable pnpm

# Common commands:
pnpm install                     # Install from lockfile
pnpm add react                   # Add dependency
pnpm add -D typescript           # Add dev dependency
pnpm remove lodash               # Remove package
pnpm update --interactive        # Interactive update UI
pnpm why lodash                  # Why is this installed?
pnpm ls                          # List installed packages
# .npmrc — pnpm configuration:
# Enforce strict peer dependencies:
strict-peer-dependencies=true

# Hoist patterns (allow certain phantom deps for compat):
public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=*prettier*

# Save exact versions:
save-exact=true

# Node linker (for compatibility with some tools):
# node-linker=hoisted  # Falls back to npm-style if needed
// pnpm-workspace.yaml — monorepo config:
{
  "packages": [
    "apps/*",
    "packages/*",
    "tools/*"
  ]
}
# pnpm workspace commands:
pnpm --filter web add react-query         # Add to specific package
pnpm --filter "!web" install              # Install all except web
pnpm -r run build                         # Run build in all packages
pnpm --filter web... run build            # Build web + its dependencies
pnpm --filter ...web run build            # Build packages that depend on web

Why pnpm Over npm

pnpm advantages:
  → No phantom dependencies (package.json must declare everything)
  → 50% less disk usage (hardlinks, not copies)
  → 3-5x faster installs than npm
  → Best workspace support (filtering, recursive)
  → Isolated node_modules (each package sees only its deps)

pnpm limitations:
  → Occasional compatibility issues with poorly-written packages
  → Slightly steeper learning curve for teams migrating from npm
  → Some tools (older ones) expect hoisted node_modules

Bun: When Speed Is Everything

# Install Bun:
curl -fsSL https://bun.sh/install | bash

# Bun install commands (compatible with npm syntax):
bun install                      # Install from lockfile
bun add react                    # Add dependency
bun add -d typescript            # Add dev dependency (note: -d not -D)
bun remove lodash                # Remove
bun update                       # Update all packages
# bun.lock — Bun's lockfile format:
# Binary lockfile (bun.lockb) in older versions
# Text lockfile (bun.lock) in Bun 1.1+
# Commit bun.lock to version control
# bunfig.toml — Bun configuration:
[install]
# Use a private registry:
registry = "https://registry.npmjs.org"
exact = true  # Pin exact versions

[install.scopes]
# Scoped registry:
"@mycompany" = { token = "$NPM_TOKEN", url = "https://npm.mycompany.com" }
# Bun workspaces:
# package.json at root:
# {
#   "workspaces": ["apps/*", "packages/*"]
# }

bun install                      # Installs all workspaces
bun add react --workspace apps/web  # Add to specific workspace
bun run --filter '*' build       # Run build in all workspaces

Bun Install Limitations

Known compatibility issues in 2026:
  → Some native binaries may not install correctly
  → Postinstall scripts: some packages assume npm/node environment
  → pnpm-specific workspace.yaml not supported (use package.json workspaces)
  → Some packages with complex resolution logic may resolve differently

Test your project before switching to Bun install in CI:
  bun install && bun test  # Quick compatibility check

npm: Universal Compatibility

# npm — the universal fallback:
npm install                      # Install
npm install react                # Add
npm install -D typescript        # Add dev
npm uninstall lodash             # Remove
npm update                       # Update

# npm workspaces (basic):
# package.json: { "workspaces": ["apps/*", "packages/*"] }
npm install                      # Installs all workspaces
npm run build --workspace=apps/web  # Run in specific workspace
npm run build --workspaces          # Run in all workspaces

Corepack: Managing Package Managers

// package.json — specify exact package manager:
{
  "packageManager": "pnpm@9.15.0"
}
# Enable Corepack (Node.js 16+):
corepack enable

# Now the packageManager field is enforced:
# If you run npm install in a pnpm project, Corepack intercepts:
# "This project requires pnpm@9.15.0. Run 'corepack use pnpm@9.15.0' to switch."

# In CI — enable Corepack before install:
corepack enable
# Then just run: pnpm install (or whatever packageManager specifies)

Decision Guide

Use pnpm if:
  → New project, want best practices
  → Monorepo with multiple packages
  → Strict dependency isolation important
  → Most compatible choice that's still fast

Use Bun (install) if:
  → Already using Bun as runtime
  → CI speed is critical and you've tested compatibility
  → Greenfield project with modern packages only

Use npm if:
  → Maximum compatibility needed (legacy projects)
  → Required by tooling that expects npm conventions
  → Team unfamiliar with pnpm/Bun
  → Deploying to environment where only npm is available

Compare package manager downloads on PkgPulse.

Comments

Stay Updated

Get the latest package insights, npm trends, and tooling tips delivered to your inbox.