pnpm vs npm vs Bun for large repos: what teams notice
pnpm vs npm vs Bun affects disk use, install time, and workspace flow. This guide compares daily team tradeoffs in large repos without hype.

Why this choice turns into daily friction
A package manager rarely causes problems on day one. The pain shows up a few weeks later, when five people pull different branches, CI runs all day, and one small dependency change makes installs crawl again. That is when pnpm vs npm vs Bun stops being a tool debate and turns into a daily team problem.
Big repos make tiny inefficiencies feel expensive. One developer waits three extra minutes for a clean install. Another loses disk space because the same packages sit in several places. A new teammate pulls the repo, runs the usual command, and workspace scripts fail because dependencies resolved a little differently than expected.
Teams usually run into the same issues: installs that feel fine on one laptop but drag in CI, duplicate files that quietly eat SSD space, workspace commands that work for one app and break for another, and lockfile changes that create noisy pull requests.
Benchmark charts barely show any of this. They tell you who won a clean install on one machine. Real work is messier. People switch branches, add one package, rerun tests, rebuild apps, and try to keep the repo stable while several projects move at once.
For most teams, the comparison comes down to three things. First is disk usage: how much space the repo and cache take after weeks of normal work. Second is install speed, including repeat installs, branch switches, and CI jobs, not just the first run. Third is workspace behavior: whether scripts, dependency resolution, and package boundaries stay predictable when many people touch the same repo.
If you lead a team, this choice shows up in support requests fast. Someone asks why local setup takes half an hour. Someone else asks why a shared package script suddenly stopped working. A good package manager does not make the repo exciting. It makes the repo boring, and that is exactly what busy teams need.
What changes when the repo gets big
A repo starts to feel large long before it looks impressive on paper. You notice it when one product turns into several apps, shared packages, internal tools, test helpers, docs, and build scripts that all depend on each other. A small change in one place can wake up half the repo.
The pattern is familiar. A team adds a web app, then an admin panel, then a mobile client, then a shared UI library, then a common API package. After that, installs happen all the time because someone is always pulling a branch, switching tasks, updating a lockfile, or adding one more dependency.
At that point, the repo usually has the same signs. Dozens or even hundreds of packages live in one workspace. Shared code sits in the middle of several apps. Fresh installs happen every day instead of once a week. One lockfile change affects people who did not touch the feature. New hires take too long to get the project running.
That last part matters more than teams expect. If local setup takes 40 minutes instead of 8, the cost spreads fast. Five developers repeating that pain across branch switches, broken installs, and machine resets can lose hours in a week without noticing. The package manager stops being background tooling and becomes part of the team’s daily mood.
CI feels this in its own way. It cares about clean, repeatable installs, cache hits, and whether a job can rebuild the repo without surprises. Developer laptops feel something else: slow cold starts, disk pressure, battery drain, and odd edge cases after months of package churn.
That difference catches teams off guard. A setup can look fine in CI but still annoy every engineer locally. Or it can feel quick on one senior developer’s tuned machine and crawl on a newer laptop with a nearly full drive.
Once the repo grows, pnpm vs npm vs Bun becomes a real team question. Package management affects onboarding speed, branch switching, dependency updates, and how often people mutter at their terminal before lunch.
How disk use differs in real projects
When teams compare pnpm vs npm vs Bun, disk use is often the first surprise. In a big repo, space does not disappear because one package is huge. It disappears because the same packages get installed again and again across apps, tools, branches, and old clones.
npm usually takes the most room over time. It keeps a full node_modules tree in each project, and even with deduping, plenty of files still get repeated. If your repo has a web app, an API, a shared UI package, test tools, and docs, the same TypeScript, ESLint, React, and test packages can sit in many places at once.
pnpm handles this differently. It keeps packages in a shared store on disk, then links them into each project. One copy of a package can back many workspaces. On a monorepo with lots of overlap, that cuts wasted space fast. The larger the repo gets, the easier it is to see the difference.
Bun also uses a global cache and tries to reuse what is already on disk. In many projects, that makes it leaner than npm. Still, teams usually see more predictable space savings with pnpm in large workspace setups because the shared store is central to how it works.
npm has a cache too, but that mostly helps downloads. It does not shrink the installed layout much. node_modules can still grow into a small forest.
On real laptops, the pattern is fairly consistent. npm fills SSD space faster, especially if developers keep several clones of the same repo. pnpm keeps repeated packages under control across workspaces and projects. Bun often lands somewhere in between, and sometimes gets close to pnpm.
This matters more than benchmarks suggest. Many developers work on 256 GB or 512 GB SSDs, and package files compete with Docker images, local databases, mobile SDKs, and browser caches. Saving even 10 or 15 GB across active repos feels very real when your machine starts warning you about storage.
Teams notice cleanup pain too. With npm, deleting node_modules can recover a lot of space, but it comes back quickly. With pnpm and Bun, shared storage means you keep less duplicate weight around in the first place. That means less housekeeping and fewer moments when a laptop slows down because dependency folders took over the disk.
What install speed feels like day to day
Raw benchmark charts miss the part teams actually feel. The painful wait usually happens after you pull a branch, clear a broken install, or open the repo on a new machine five minutes before a meeting.
In a large repo, package manager choice shows up in three moments. The first install is the slow and expensive one. Repeat installs are what people hit most days. A clean install sits in the middle: you already know the repo, but you wipe node_modules and start over because something drifted.
For a first install on a fresh laptop or a clean CI runner, network speed often sets the pace. If the office Wi-Fi is shaky, the VPN adds latency, or the registry proxy is slow, the fastest tool on paper may not feel much faster. Bun often looks very quick here, especially when it can fetch and link packages fast. npm has improved a lot, but in very large repos it still tends to feel heavier. pnpm is usually strong too, although its biggest win often shows up after the first install.
Warm cache results matter more for daily work. Once packages already exist on the machine, pnpm often feels snappy because it reuses content well instead of copying the same files again and again. That saves time when developers switch branches or update one workspace package. Bun can still feel quick, but teams should test it against their own scripts and postinstall steps. npm is usually fine for smaller projects, yet repeated installs in big monorepos can still drag.
The moments people notice most are simple: the first clone on a new machine, a branch switch after lockfile changes, a reinstall after deleting node_modules, a CI job on a clean runner, and a patch release where only a few packages changed.
Lockfile consistency changes the story more than many teams expect. If everyone uses the same tool and keeps one lockfile stable, installs stay predictable. If developers mix tools, churn the lockfile, or trigger full re-resolution, any speed edge disappears fast.
That is why pnpm vs npm vs Bun is less about one benchmark and more about how often your team waits during an ordinary week.
How workspaces behave when many people touch the repo
In a small repo, workspaces feel tidy. In a large repo with a web app, an admin app, and shared packages, they shape daily habits. The package manager decides how easy it is to add one dependency, run one script, and avoid breaking someone else’s part of the tree.
npm, pnpm, and Bun all support multi-package repos, but they feel different. npm uses workspaces in the root package.json, which keeps setup simple. pnpm usually adds a pnpm-workspace.yaml, and that extra file makes the workspace layout more explicit. Bun also reads workspaces from the root and looks close to npm on the surface, but some teams still find its script and tool compatibility less predictable.
The first friction point is adding a package to one app instead of the whole repo. New team members often run an install from the root and accidentally change the wrong package.json. npm supports targeting a workspace, but people need to learn that flag early. pnpm gives you the same control, and many teams like its filtering model once they get used to it. Bun can target one workspace too, though teams often end up running commands from inside the package folder because that feels safer.
Running scripts across many packages is the next test. This is where daily work either stays calm or turns noisy. npm can run scripts in workspaces, but the commands can feel clumsy when you need fine control. pnpm is usually the most comfortable in big repos because its filtering is clear and fast for cases like "run this in app A and shared package B." Bun is quick, and that speed is nice, but teams should check how their existing scripts, shell usage, and build tools behave before they trust it across the whole repo.
The biggest surprise for new people often comes from dependency visibility. pnpm is stricter, so it exposes missing or undeclared dependencies sooner. That can feel annoying for a day or two, then it saves time because packages stop relying on things they never declared. npm’s hoisting can hide that problem longer. Bun’s surprises usually come from command differences and smaller gaps around tooling.
For busy teams, that matters more than a benchmark chart. If ten people touch the repo every week, the best workspace setup is the one that makes the right action obvious and the wrong action hard to do.
How to test all three in your own repo
A fair package manager test is boring on purpose. Use one branch, pin the Node version, and freeze dependency versions before you start. If someone updates packages halfway through, the numbers stop meaning much.
Keep the app code the same for every run. Only switch the package manager and its lockfile. After each test, reset the repo to the same clean commit so pnpm, npm, and Bun each get the same starting point.
A simple comparison usually needs five runs per tool:
- Fresh install on a clean checkout.
- Repeat install with caches already warm.
- Add one new package to a workspace your team touches often.
- Run the workspace commands people use every day.
- Run the same install in CI.
Time each step with a stopwatch or shell timing, but do not stop at wall clock time. Measure disk use too. Check the size of node_modules inside the repo, then check the package manager’s cache or store after the run. That matters in large repos because pnpm often saves space through its shared store, while npm and Bun can feel different depending on how much they cache outside the project.
Workspace behavior needs its own test because speed alone does not tell the whole story. Use the commands your team already runs: install from the repo root, add a dependency to one package, run tests for one workspace, and run a filtered build. If developers work in a monorepo with many packages, small command differences can waste time every day.
Use two developer machines, not one. A fast laptop with a warm SSD can hide problems that show up on an older machine. Then repeat the same steps in CI, where cold caches and fresh containers often change the result.
Write the results in a small table. Track fresh install time, repeat install time, one-package add time, repo node_modules size, global cache size, and any command that felt awkward or failed.
That last column matters more than people admit. In a real team, the best result is not the package manager that wins one benchmark. It is the one that stays predictable on laptops, in CI, and across the workspace commands people run every week.
A simple team scenario
Picture a team of eight people working in one repo. They have a web app in apps/web, an API in apps/api, and a few shared packages for UI, types, and auth helpers. Nobody argues about package managers on day one. They start arguing when a new hire opens the repo on a fresh laptop and waits for everything to install.
With npm, onboarding feels familiar. Most developers already know the commands, so nobody stops to ask basic setup questions. The downside shows up fast: the install on a clean machine often takes the longest, and the local node_modules footprint grows fast when the repo has several apps and shared packages.
pnpm usually makes a better first impression on disk use. A new developer pulls the repo, installs once, and the shared store cuts a lot of duplicate files. In a large repo package manager comparison, that matters more than people expect because every branch switch, clean install, and CI cache restore repeats the same cost.
Bun often wins the race on raw cold install speed. A new hire can get the web app and API running sooner, which feels great on Monday morning. The catch is that big teams do not live on install speed alone. If one workspace script, postinstall step, or older package behaves oddly, the time saved at install can come back as debugging time.
A normal week makes the differences clearer. Two developers update frontend packages, one person bumps an API dependency, and CI runs on every pull request. The lockfile changes almost every day.
pnpm tends to save time across the whole week because it handles workspaces cleanly and keeps disk usage under control. It can also expose missing dependency declarations that npm may let slide. That strictness is useful, but it can confuse teams that relied on accidental hoisting for months.
npm adds the least confusion at first because everybody knows it. Still, in a busy monorepo, that comfort fades when installs stay slow and CI caches get heavy.
Bun is the wild card in pnpm vs npm vs Bun. It feels fast, and some teams love it. For a large repo with many contributors, I would pick it only after a few weeks of real CI runs, lockfile churn, and branch switching. A tool that saves 40 seconds on install but adds one strange workspace issue every few days is not actually saving time.
Mistakes that skew the comparison
A fair pnpm vs npm vs Bun test is harder than it looks. Teams often try each package manager for ten minutes, glance at install time, and call it done. That usually measures the test setup, not the package manager.
The most common mistake is cache mismatch. If one run uses a warm local cache and another starts cold, the result says more about your laptop history than real install speed. Run each package manager more than once, and label the runs clearly. Cold install, warm install, and repeat install are different situations.
Branch switching can distort the picture too. In a busy repo, developers jump between branches all day. If the lockfile changes and one package manager handles that transition cleanly while another leaves stale modules behind, people feel that pain fast. A package manager that looks quick in a fresh clone can feel messy after a week of real branch churn.
Workspace behavior is easy to misread when the sample repo is too small. A tiny demo with three packages does not show what happens when dozens of apps and shared libraries move together. Hoisting, linking, script execution, and dependency boundaries start to matter when many people touch the same repo. That is when small quirks turn into support tickets.
Copied benchmarks are another trap. A claim from an unrelated project may come from a different operating system, network setup, CI cache, dependency graph, or workspace shape. If your repo has native modules, private packages, or lots of internal libraries, outside numbers can mislead you.
One more mistake is switching before you check the rest of the workflow. Editor plugins, CI runners, Docker builds, cache setup, and deployment scripts all affect daily use.
A simple check helps: test all three with cold and warm installs, switch branches with real lockfile changes, run the full workspace instead of a toy repo, and verify editor, CI, and container support first.
That takes longer than a quick benchmark, but it gives you results your team can trust.
Quick checks before you choose
Teams often compare package managers by reading benchmark charts, then miss the habits that create most of the pain. A faster install on paper will not help much if your team rarely installs from scratch, works on small SSDs, or depends on workspace commands that feel different every day.
Before you pick between pnpm vs npm vs Bun, ask a few blunt questions and answer them with real numbers from your repo.
- How often do people do a clean install? If developers wipe
node_modulesonce a month, install speed matters less than consistency. If they rebuild often because they switch branches, test many apps, or onboard contractors, speed matters a lot more. - How much free disk space do people actually have? A senior engineer with a large desktop drive and a designer on a nearly full laptop do not feel the same setup cost. Check the machines your team really uses.
- Which workspace commands show up every week? Look at the commands people run for filtering, bootstrapping, testing one app, or building one package. A tool that feels fine for single-package work can get annoying in a busy monorepo.
- Do CI runners and local machines use the same tool version? If local installs use one version and CI uses another, teams lose hours on lockfile churn and weird failures. Pin the version and keep it the same everywhere.
- How much behavior will your team tolerate relearning? Some teams adapt fast. Others lose momentum when command flags, lockfile rules, or workspace defaults change. That cost is real, even if nobody writes it into the evaluation sheet.
A simple example helps. If your repo has 40 packages, two CI environments, and a team that switches branches all day, small differences in install behavior stack up fast. If the repo has six packages and stable workflows, the cheapest choice may be the one your team already knows.
Pick the tool that causes the fewest repeated annoyances, not the one that wins the nicest demo.
What to do next
Pick the tool that fits how your team already works. Hype fades fast when ten people touch the same repo, CI runs all day, and one broken install stalls a release.
A short trial tells you more than a week of debate. Run it in one active branch, with the same lockfile rules, the same CI steps, and the same people doing their normal work. That is how you find out whether pnpm vs npm vs Bun feels better in your repo, not someone else’s benchmark.
Write down what happens during the trial. Keep it boring and measurable:
- fresh install time on a clean machine
- repeat install time after the cache warms up
- disk use for the repo and global store or cache
- workspace issues, such as linking confusion or broken scripts
- CI behavior, especially cache hits and failed installs
Numbers help, but team friction matters just as much. If developers keep asking why a package is missing, why a script behaves differently, or why one workspace cannot see another, that cost is real even if install speed looks great on paper.
It also helps to test with one recent change that touches several packages. A large repo package manager can look fine in a simple demo and then get annoying when people rename packages, update shared dependencies, or switch branches all day.
If you want an outside view before making the call, Oleg Sotnikov at oleg.is does this kind of Fractional CTO work. He advises startups and small or medium businesses on architecture, infrastructure, and migration risk, which is often what a package manager switch turns into.
After a week or two, the pattern is usually clear. Keep the tool that causes the fewest daily interruptions, write down the rules for using it, and move on.
Frequently Asked Questions
Which package manager should a large repo team start with?
For most large repos, start with pnpm. It usually gives teams the best mix of lower disk use, fast repeat installs, and clearer workspace rules. Stick with npm if your repo is smaller or your team needs the most familiar setup. Try Bun only after a real trial in your repo, because speed alone does not cover script and tooling quirks.
Is Bun always the fastest choice?
No. Bun often feels fastest on a fresh install, but daily work includes branch switches, warm caches, CI runs, and postinstall scripts. If those parts get weird, the time you save on install can disappear fast.
Why does npm usually take more disk space?
npm usually stores a full node_modules tree inside each project, so the same packages get copied many times. In a monorepo with several apps and shared packages, that duplication adds up quickly. pnpm cuts more of that waste because it reuses one shared store.
Does pnpm break packages in a monorepo?
pnpm does not break healthy packages. What it often does is expose packages that relied on undeclared dependencies. That can feel annoying at first, but it usually leads to a cleaner repo because each package declares what it really needs.
When is npm still the right pick?
npm still makes sense when your team wants the least change and the repo is not very large. It also works well when everyone already knows the workflow and disk use has not become a problem. If installs stay acceptable and CI stays stable, familiarity can win.
What should we measure before switching tools?
Measure fresh install time, warm install time, disk use in the repo, cache or store size, branch switch behavior, adding one dependency to one workspace, and CI reliability. Those numbers show more than a single benchmark because they match normal team work.
Do benchmark charts matter much?
Benchmarks help as a first glance, but they do not settle the choice. They rarely show lockfile churn, branch switching, workspace scripts, or tool compatibility. Use them to form a guess, then test that guess in your own repo.
How long should we trial pnpm, npm, or Bun?
Give it at least one or two weeks on an active branch. Let the team do normal work, including dependency updates, branch switches, clean installs, and CI runs. A short real trial tells you more than a polished demo.
Will one lockfile fix most install problems?
A stable lockfile helps a lot, but tool and version consistency matter just as much. If some people use one package manager and others use another, churn starts fast. Pick one tool, pin the version, and keep local and CI the same.
What mistakes make package manager comparisons useless?
Teams often compare a warm cache run against a cold cache run, or they test on a tiny sample repo that does not match real work. They also forget CI, Docker builds, editor support, and branch switching. Test the full workflow, not just one install command.