pnpm 12’s Rust Rewrite Cuts Install Times by Up to 90%

pnpm 12 rewrites the package manager in Rust, cutting install times by up to 90% while preserving pnpm 11 workflows and lockfiles.

  • Sarah Gooding
    Sarah Gooding
6 min read
pnpm 12’s Rust Rewrite Cuts Install Times by Up to 90%

pnpm 12 is now stable, replacing the package manager’s Node.js and TypeScript foundation with a Rust rewrite while preserving the commands, settings, and lockfile format used by pnpm 11. Early results from a large production monorepo show install times falling by as much as 90%, although a dispute over flawed and outdated package manager benchmarks has complicated broader claims about where pnpm now ranks against Bun and other rivals.

Released August 26, pnpm 12 is designed to be a major implementation change without becoming a migration project for users. Existing scripts and workflows should largely carry over, and the same documentation applies to pnpm 11 and 12. As of publication, npm’s latest tag still points to pnpm 11, so pnpm 12 must be installed from next-12. Users on pnpm 11.10 or newer can switch with:

pnpm self-update next-12

A Rust rewrite that is meant to feel like pnpm 11

The rewrite moves pnpm’s performance-sensitive work into a native Rust binary, removing much of the overhead that comes from starting a JavaScript runtime and routing a large volume of filesystem work through Node.js. Package installation is dominated by fetching metadata and tarballs, unpacking files, resolving dependency graphs, and linking packages into node_modules, making it a natural target for native code and parallelism.

pnpm 12 retains the existing CLI, configuration, lockfile format, and content-addressable store that lets projects share package files instead of keeping a separate copy for every installation.

The approach is already producing substantial gains outside pnpm’s own test suite. When Vercel upgraded the 21-project Turborepo workspace, which installs 1,670 packages, pnpm 12 reduced median install times by 64.4% to 90.5% compared with pnpm 10.28 across six combinations of warm and cold stores, existing and absent node_modules, and enabled or disabled lifecycle scripts.

The largest reduction came when node_modules was already present: 1.476 seconds fell to 142 milliseconds with a warm store, and 1.385 seconds fell to 141 milliseconds with a cold one. With both the store and node_modules absent and lifecycle scripts enabled, the median dropped from 9.850 seconds to 3.472 seconds.

Those results came from 20 measured runs per version on the same Linux system, offering a more useful view of the upgrade than a one-off package manager race. They also exposed a tradeoff. pnpm 12’s native Corepack artifact was 47.3 MB, compared with 17.5 MB for pnpm 10.28, making an uncached Corepack startup 11.1% slower. Once cached, startup was 74.7% faster. The combined pnpm store and node_modules footprint also fell 52.5%, from 3.891 GB to 1.850 GB on the test system.

pnpm joins the Rustification of JavaScript tooling

The release extends a years-long shift in which JavaScript tools keep their interfaces while moving performance-critical internals into native languages. Rust already powers projects including SWC, Biome, Oxc, Rolldown, and parts of Turbopack. pnpm is now applying the same model to one of the most frequently executed pieces of the development workflow.

pnpm lead maintainer Zoltan Kochan framed the release as part of a broader migration of Node.js package managers to Rust. In the ensuing discussion, former npm CLI maintainer Darcy Clarke argued that the trend also reflects Node.js developer-experience shortcomings and its slow progress on single-executable applications and foreign-function interfaces. Clarke added that keeping package managers in JavaScript or TypeScript makes it easier for them to share and improve common internals.

Kochan’s reply captured the frustration behind pnpm’s move: “It was faster to rewrite pnpm in Rust than to migrate to ESM.” He added that he regretted moving pnpm 11 to ESM.

The tradeoff is larger than language preference. Native rewrites can sharply reduce startup and filesystem overhead, but JavaScript implementations are easier for the Node.js ecosystem to inspect, extend, and reuse. pnpm 12 is an unusually ambitious attempt to take the performance benefit without forcing users to absorb a new package manager model.

pnpm narrows its public benchmark claims

A previous version of pnpm’s benchmark page compared pnpm 12 with Bun and Yarn using August 14 results that predated several fixes to pnpm’s benchmark harness.

One bug let pnpm 12 reuse package metadata during supposedly clean installs, while another update test gave Bun a warm cache and pnpm a cold one. The Vlt benchmark suite had a separate parsing bug that failed to count pnpm 12’s installed packages, leaving its total duration in seconds alongside competitors measured in milliseconds per package. That fix was merged August 28.

The errors pushed results in different directions, but they made the published cross-tool rankings unreliable. pnpm has since removed Bun and Yarn from the comparison displayed on its website. The harness will continue measuring them internally, while the public page now compares pnpm with npm and pnpm’s previous JavaScript implementation. Kochan said he could not currently claim pnpm was the fastest package manager and would no longer publish comparisons with rivals other than npm.

The narrower claim is better supported by the available evidence. pnpm 12 is substantially faster than earlier pnpm releases across both its corrected tests and Vercel’s repository-specific measurements. Small differences in cache state, security checks, network modeling, and package counts make universal package manager rankings far harder to defend.

Security and reproducibility change alongside the engine

Performance is the headline, but pnpm 12 also adds several changes relevant to software supply chain security. Some of the major highlights include:

  • Project-aware global bins: A globally installed node, deno, or bun can follow the version pinned by the current project. Stable Node.js releases are signature-verified, while other runtimes, prereleases, and user-enabled binaries require a per-project trust prompt.
  • Direct package manager provisioning: pnpm can install npm, Yarn, Bun, Node.js, and Deno. Tools distributed through npm are verified against npm’s signature for the requested version, allowing Git-hosted dependencies to use their specified package manager even when only pnpm is installed.
  • Registry revisions: The new registry revisions mechanism lets registries provide a patched artifact for an existing version without overwriting the original name@version bytes. pnpm identifies the replacement by its SHA-512 digest and records the revision in the lockfile.
  • Signed remote build artifacts: A proof-of-concept remote side-effects cache through pnpr can restore signed, organization-scoped build outputs instead of rerunning lifecycle scripts. Signing configuration stays outside pnpm-workspace.yaml, preventing a cloned project from repurposing the machine’s key. Support is currently limited to Linux with glibc on x64 and Arm64.
  • Deterministic cyclic lockfiles: pnpm 12 breaks dependency cycles at a fixed point, producing byte-identical lockfiles regardless of dependency ordering or traversal path. On cycle-heavy workspaces, pnpm reports two to three times faster peer resolution, roughly 25% lower memory use, and smaller lockfiles.

These additions broaden pnpm 12 beyond performance. Teams considering the upgrade should also review the smaller set of behavioral changes that may affect existing workflows.

What changes when upgrading

The project published a separate compatibility guide covering seven behavioral differences. The change most likely to stop an existing CI job is the removal of pnpm install --resolution-only; pnpm peers check now handles its former peer-dependency reporting role.

Git dependencies hosted on GitHub, GitLab, and Bitbucket also resolve through each host’s canonical HTTPS URL rather than recording a machine-specific SSH transport in the lockfile. Private SSH access now depends on Git URL rewriting configured on the machine. On Linux, packageImportMethod: auto tries hardlinks before reflinks, while macOS remains clone-first.

pnpm 12 additionally reports unknown settings in pnpm-workspace.yaml instead of silently ignoring them, an important correction for misspelled security controls such as minimumReleaseAge. Global commands that modify the pnpm installation now refuse to run under sudo, avoiding accidental changes to the root user’s pnpm home.

The release establishes Rust as pnpm’s new foundation without asking teams to change how they manage dependencies. Its early performance results are strong, particularly within the same repository and workload. The rewrite places pnpm among the growing list of JavaScript tools moving performance-critical infrastructure into Rust.

Stay ahead of threats

Subscribe to our newsletter

Get notified when we publish new security blog posts!