What does Vercel actually cache during a build?
Vercel’s build cache is path-based. For a typical Next.js project, the cached locations are node_modules, .next/cache, and the lockfile, according to the 2024 Berry-on-Vercel writeup by Adriel Martinez. Anything outside that set is re-fetched or rebuilt on every deploy. That assumption holds when the package manager lays dependencies out under node_modules, which is what npm and Yarn Classic do. It breaks for layouts that do not.
Yarn Berry does not populate node_modules by default. It replaces the directory with a single .pnp.cjs resolution file and stores packages as compressed archives under .yarn/cache, as a Yarn-vs-Yarn-Berry comparison lays out. That layout is the basis of Yarn’s zero-install model, and it is structurally different from what Vercel’s classic cache path assumed. The consequence, documented in the 2024 post, is that .yarn fell outside the cached set and the fetch step ran cold on every build.
Did Vercel ship a Yarn Berry caching fix in 2026?
Not in any public source that could be verified. Vercel’s aggregated release notes on Releasebot show the platform actively shipping build and runtime performance work through 2026, but no entry adds Yarn 2+ dependency caching to the build-cache path. The feed’s recent items run toward deployment protection, the AI gateway, and firewall surface area rather than package-manager install caching.
The last direct documentation of Berry caching behavior on Vercel is the February 2024 post, which predates Vercel’s Fluid Compute model and the current Agents, Apps, and Platforms product structure by over a year. Vercel could have closed the gap silently in a build-image change without a changelog line, and the absence of a release note is not proof the gap persists. But “could have” is not a basis for a claim, and the documented state is the opposite of cached.
How does Yarn Berry’s caching actually work?
Berry has two distinct caching models, and conflating them is where most of the confusion starts.
The first is Plug’n’Play (PnP). With PnP enabled, Yarn writes a .pnp.cjs loader that tells Node where every dependency lives, and stores the packages themselves as gzipped archives in a cache. No node_modules is produced. According to Yarn’s caching documentation, PnP loaders are byte-identical regardless of which machine generated them, and the offline cache holds every file the loaders reference.
The second is zero-install, the stricter subset. Setting enableGlobalCache to false writes the package cache to a local, committable .yarn/cache, per the same Yarn docs. Combined with PnP, that makes a git checkout effectively stand in for yarn install. Zero-install restores are deterministic across CI runners and immune to npm registry outages, with one caveat: adding or removing packages with native dependencies still requires a real yarn install.
The practical split matters here. A zero-install Berry project already skips resolution on Vercel, because the dependencies are committed to the repo. A node-linker Berry project, the fallback mode that does write to node_modules, is the configuration that historically re-fetched every build.
Why .yarn fell outside Vercel’s cached paths
The 2024 post isolates the cause precisely. Vercel detects the package manager from the committed lockfile, and at the time only Yarn Classic appeared on its supported-package-manager table. The .yarn folder, which contains Berry’s cache, was not in the cached set of node_modules, .next/cache, and yarn.lock. The fetch step had nothing to restore from, so it re-resolved every dependency from the registry on each build.
The numbers from that repro are the clearest measure of the penalty. On a Berry project with Next.js, the fetch step took 2 minutes 52 seconds and the link step took 1 minute 6 seconds, per the Adriel Martinez post. For a hobby-tier project deploying on every push, that is the cost of every build, spent on work the cache should have absorbed.
The workaround, and what it actually saved
The post’s workaround has two moves. First, point Yarn’s own cache at a Vercel-cached location by exporting YARN_CACHE_FOLDER=./.next/cache/yarn before the install. That relocates Berry’s package archive cache inside .next/cache, which Vercel does restore. Second, round-trip .yarn/install-state.gz through .yarn/ so the link step hits cache: copy node_modules/install-state.gz into .yarn/ before install, copy it back after, and let the cached path persist it across builds.
The before-and-after is stark. With YARN_CACHE_FOLDER relocated, the fetch step dropped from 2m52s to roughly one second. With install-state.gz round-tripped, the link step dropped from 1m6s to roughly one second, on the same project. The cold-resolution penalty was on the order of minutes per build before caching was wired in by hand.
This is the part that matters for monorepo CI cost. Vercel’s build minutes are finite, as the Adriel Martinez post notes, and a monorepo with a large dependency graph paying three to four minutes of install on every deploy burns through that budget on install alone, before any actual build work runs.
What governs the cache-hit rate on Berry
If and when Vercel does cache Berry installs natively, hit rate will hinge on cache-key invalidation, not on the size of .yarn/cache. The reason is structural. PnP’s .pnp.cjs is a single resolution file, and Berry stores packages as content-addressed archives. The cache key is effectively the lockfile hash plus the .pnp.cjs hash, not a node_modules tree walk.
That has a counterintuitive consequence for monorepos. Adding or upgrading a single dependency changes the lockfile and regenerates .pnp.cjs, invalidating the cache key for the whole workspace even though most archives on disk are unchanged. The fetch step still has to run, but it should be near-instant because the archives themselves are cached and Berry only re-fetches the diff. The expensive parts are the resolution and link steps, which is exactly what the 2024 workaround targeted.
For monorepo workspaces, pinning matters more than usual. A floating version range that resolves differently between builds will churn the lockfile, regenerate .pnp.cjs, and depress the hit rate. Deliberate version pinning, and keeping dependency upgrades in their own commits, keeps the cache key stable.
How Berry compares on raw install speed
Caching aside, Berry is not the fastest installer on raw throughput. A 2026 three-way comparison by Better Stack rates Berry’s install performance as similar to npm but with faster subsequent runs, while PNPM is faster than npm on install and Bun Install is 20-30x faster. Berry is the only one of the three that replaces node_modules rather than populating it.
| Installer | Cold install vs npm | Package layout |
|---|---|---|
| npm | baseline | node_modules |
| Yarn Berry | similar; faster subsequent runs | .pnp.cjs + archives (replaces node_modules) |
| PNPM | faster | symlinked node_modules |
| Bun Install | 20-30x faster | node_modules |
The cold-install column is where the Vercel caching gap hurts most. Berry’s subsequent-run speed only pays off if the cache survives between builds, which on Vercel historically required the manual workaround above.
Does any of this remove the reason to stay on Yarn Classic?
Not on the evidence available. The reason teams stayed on Yarn Classic for Vercel deploys was that Classic’s node_modules layout sat inside the cached paths and got restored for free. Berry’s layout did not, and the fix was a hand-rolled shell script. Until Vercel documents Berry support on the build-cache path, the migration penalty the 2024 post describes is still the documented state.
Vercel, founded as ZEIT in 2015 and rebranded in April 2020, creates and maintains Next.js, per Wikipedia. Its current homepage markets an agentic-infrastructure lineup that includes a compute model called Fluid Compute. The company ships fast, and a build-image change closing the Berry gap could land without ceremony. But shipping fast is not the same as having shipped this specific fix, and the secondary coverage that would confirm it does not exist in the sources surveyed.
For zero-install Berry monorepos, nothing needs to change: the install step is already a no-op via the committed cache. For node-linker Berry monorepos, the documented state as of the most recent primary source is still the 2024 gap and the manual workaround. Verify against Vercel’s own build-cache documentation before assuming otherwise.
Frequently Asked Questions
Does the caching gap affect PNPM or Bun monorepos on Vercel too?
No. PNPM writes a symlinked node_modules and Bun Install writes a conventional node_modules, so both land inside Vercel’s cached paths and restore for free. The gap is specific to Yarn Berry’s PnP layout, the only major installer that replaces node_modules rather than populating it.
What did Vercel actually ship in its June 2026 release window?
The aggregated release feed lists zero-config Node server deploys, custom OIDC token audiences, deploys from Claude Design, a redesigned Workflows trace viewer, Chat SDK integrations with Kapso, Novu, Sendblue, and Linq, and a Workflow Development Kit whose turbo mode skips the initial event-log load. None of those items touches the Yarn Berry install-cache path.
When does zero-install still force a real yarn install on Vercel?
Native dependencies break the committed-cache guarantee. Packages that ship platform-specific binaries, such as esbuild, sharp, or anything built with node-gyp, must be fetched for the build runner’s exact architecture, so a git checkout cannot stand in for yarn install when those packages are added or upgraded.
How would a team detect that Vercel silently closed the Berry caching gap?
Strip the YARN_CACHE_FOLDER workaround from a node-linker Berry project and watch the fetch-step duration in the build logs. A drop from roughly three minutes to under a second indicates native caching landed; a fetch that stays in the minutes range means the documented gap still applies.
Which Yarn and Next.js versions were used in the 2024 caching repro?
The 2024 post ran Yarn 4.1.0 against Next.js 14.1.0. Both have moved past those majors since, but the structural cause, Berry’s non-node_modules layout, is unchanged by version bumps, so the caching behavior should hold regardless of which Berry or Next.js version a monorepo pins.