The monorepo question refuses to die because the math keeps shifting under teams' feet. What worked at five packages breaks at fifty. What feels overengineered at fifty starts feeling like the only sane option at two hundred.
We took the same TypeScript codebase, ran it through Turborepo, Nx, and bare pnpm workspaces at two different sizes, and measured every CI run plus every configuration hour. The gap between the three tools is bigger than the surface comparisons suggest, but the right pick depends on a number most teams underestimate.
The Monorepo Question That Refuses To Die
Every six months somebody publishes a fresh take. The takes age badly because the tooling keeps changing under them.
In 2026 the picture finally settled. Turborepo is the simple task runner with caching, Nx is the full framework with project graph analysis, and pnpm workspaces alone is the minimum-viable substrate both tools sit on top of. The decision is not whether to use a monorepo, it's which orchestration layer earns its complexity at your repo size.
If your team can't articulate why they picked the tool they picked, they probably picked wrong. The fastest way to regret a monorepo decision is to copy somebody else's stack without copying their constraints.
Polyrepo: Where Independence Still Beats Coordination
Before defending the monorepo, name what polyrepos still do well. Independence is the obvious one. Each service ships on its own cadence, each team owns its own release calendar, each repo runs its own CI without anybody else's failing test blocking the merge.
For organizations with strong service boundaries and weak shared code, polyrepo is genuinely the right answer. We migrated a five-service backend out of a monorepo in 2025 because the coupling was imaginary, not real. Every service used Postgres differently, every service had its own deploy cadence, and the shared utils package was thirty lines of date formatting nobody actually shared.
The trap is when you have real shared code, multiple teams making changes, and a refactor that needs to touch four repos atomically. That is where polyrepo turns into a tax.
pnpm Workspaces Alone: The Minimum That Works
pnpm workspaces is not a competitor to Turborepo or Nx. It's the foundation both tools sit on. The workspace feature handles package linking, deduplication, and the symlinked node_modules layout that makes monorepos efficient on disk.
You can absolutely run a small monorepo on pnpm workspaces alone. No remote cache, no project graph, just pnpm -r build running tasks across every package in dependency order. For three or four packages this is fine. The build is fast enough, the configuration is one root pnpm-workspace.yaml file, and there is nothing to debug when a task fails.
The wall hits around package eight. CI starts taking ten minutes instead of three. Every change rebuilds everything because pnpm has no concept of "this package didn't change, skip it." That is when you start shopping for a cache.
Turborepo: Caching As The Whole Pitch
Turborepo's pitch is one sentence. Cache task outputs based on input hashes, so unchanged work gets skipped. Everything else is window dressing.
The setup is genuinely minimal. Add a turbo.json at the root, define which tasks depend on which, set the inputs and outputs per task, and Turborepo handles the rest. On a five-package monorepo the configuration runs about forty lines and the learning curve is one afternoon.
The remote cache is where Turborepo earns its keep on real teams. Vercel's hosted cache is free for teams up to a few seats, and self-hosting via Turborepo's remote cache spec is a one-day project. Once the cache is shared across CI runners and developers, the build that took eight minutes on first run takes ninety seconds when somebody else has already built the same code.
Nx: When The Generator Toolkit Earns Its Keep
Nx is a different category of tool. It's not a task runner with caching bolted on, it's a full monorepo framework that understands every file, every import, and every project boundary in your repo.
The project graph is the killer feature. Nx parses your code, builds a dependency graph, and uses it to figure out which projects are affected by any given change. Run nx affected --target=test and Nx tests only the projects that could have broken, skipping everything else. On a fifty-package monorepo this is the difference between a thirty-minute CI run and a ninety-second one.
The generator toolkit is what pushes Nx past Turborepo for larger teams. Nx ships generators for libraries, applications, components, and full Next.js or NestJS scaffolds. A new package goes from "thirty minutes of copy-paste from another package" to nx g @nx/react:library my-feature and you're done. At scale this matters because consistency matters.
The cost is real. Nx is a framework, not a library. The nx.json plus per-project project.json configuration is several hundred lines on a real repo. Migrations between Nx major versions take a day. Documentation is excellent but the surface area is large.
Five-Package Migration Across All Three
We took a five-package TypeScript repo (one Next.js app, one Express API, one shared types package, one UI component library, one shared utils) and migrated it through all three approaches.
Bare pnpm workspaces took about twenty minutes to set up. Three lines in pnpm-workspace.yaml, package.json adjustments per package, done. The first CI run took six minutes (build + test across all packages). Every subsequent run also took six minutes because nothing was cached.
Turborepo took roughly one hour to migrate cleanly. The turbo.json took thirty minutes to get right (mostly figuring out which outputs to cache per task), and the rest was untangling a couple of inputs that crossed package boundaries. First CI run was the same six minutes. Second run with cache hits dropped to fifty-five seconds.
Nx took a full day. The Nx init script handles the bones quickly, but the per-package project.json files need attention, and the migration path from "pnpm workspaces I wrote myself" to "Nx-managed projects" required some surgery. First CI run took five minutes (Nx's task pipeline is slightly more efficient out of the box). Second run with cache and affected-only was under forty seconds.
At five packages, Turborepo's one-hour setup beats Nx's full-day setup unless you genuinely need code generators on day one. The cache wins are nearly identical at that size.
Twenty-Five-Package Migration And Where Tools Diverge
Five packages is the easy case. Twenty-five is where the tools' philosophies start mattering.
We took the same approach on a real codebase with twenty-five packages. Three apps (web, mobile, admin), four shared libraries (UI, utils, types, hooks), six API services, and twelve internal feature packages.
pnpm workspaces alone hit a wall hard. CI runs averaged twenty-four minutes because everything rebuilt on every change. The team gave up after one sprint and started shopping.
Turborepo handled twenty-five packages well, but the turbo.json grew to a couple hundred lines with task-specific overrides per package. First CI run was twenty-three minutes. Subsequent runs with cache averaged three minutes. The pain point became invalidation, every time we touched a deeply-nested shared package, half the cache invalidated because Turborepo's hashing follows the dependency graph aggressively.
Nx pulled ahead clearly. The nx affected command meant changes to a single service rebuilt that service plus its dependents only. Median CI time dropped to ninety seconds for typical commits. The generators paid off, six new feature packages were scaffolded in fifteen minutes total versus an estimated four hours of copy-paste.
CI Minutes Saved Versus Configuration Hours Paid
Configuration time is the cost most articles skip. Both Turborepo and Nx have ongoing maintenance overhead, not just initial setup.
On the five-package repo, Turborepo cost about three hours per quarter in maintenance (cache misses, new package onboarding, occasional turbo.json tweaks). Nx cost about eight hours per quarter, mostly because Nx version upgrades require attention and the larger configuration surface area has more places to drift.
On the twenty-five-package repo, the numbers flipped. Turborepo maintenance scaled linearly with packages, about eight hours per quarter. Nx held steady at ten hours per quarter because the project graph and generators absorbed most of the new-package overhead.
The break-even point in our testing was around fifteen packages. Below that, Turborepo's lower complexity wins. Above that, Nx's structural understanding starts paying back the configuration cost.
Picking The Right Tool By Repo Size And Team Shape
The honest decision tree is shorter than the comparison articles suggest. Under five packages, run pnpm workspaces alone unless CI time is already a complaint. Five to fifteen packages with a small team, Turborepo is the right pick. Fifteen-plus packages or a team large enough that generators and architecture enforcement matter, Nx pays off.
Multi-language is the asterisk. Nx handles Go, Rust, Python, and other ecosystems through its plugin system in a way Turborepo doesn't even attempt. If your monorepo includes a non-JS service and you want unified tooling, Nx is the only real option.
The other consideration is team shape. Nx's plugin system and generator toolkit assume you have somebody (probably a platform engineer) who owns the monorepo tooling. If nobody on the team wants that role, Turborepo's lower surface area is safer because it stays out of your way.
The tool you don't maintain is more expensive than the tool you maintain. Pick the one your team will actually invest in or you'll fight the configuration forever.
Related Reading
For more context on developer tooling decisions, see our breakdowns of Cursor vs Windsurf vs Claude Code and GitHub vs GitLab 2026. The AI coding assistants guide covers how these monorepo decisions affect your AI-assisted workflow.
FAQ
Is Turborepo still relevant after the Vercel acquisition?
Yes. Vercel acquired Turborepo in 2021 and has invested heavily in it since. The remote cache is free for small teams, the OSS project ships features regularly, and self-hosting the cache is well-documented. The acquisition concern is real for some teams but the tool itself remains the simplest option in the space.
Can you switch from Turborepo to Nx later?
Yes, with about a week of migration work on a medium-sized repo. The pnpm workspaces foundation stays the same, so package layout doesn't change. The work is replacing turbo.json with nx.json plus per-project project.json files and updating CI commands. Plan a quiet sprint for it.
What about Bazel or Moon?
Bazel is the right answer if you're Google or have Google-scale problems. The configuration cost on a typical JS/TS monorepo is too high to justify. Moon is interesting but the ecosystem and remote cache story isn't where Turborepo or Nx are in 2026, so we don't recommend it for production teams yet.
Does pnpm work with Turborepo and Nx?
Both Turborepo and Nx support pnpm, npm, and Yarn workspaces. pnpm is the recommended choice for both because the symlinked node_modules layout is more disk-efficient and avoids the hoisting issues npm has historically had.
Do we still need Lerna in 2026?
No. Lerna was the original monorepo tool but it was effectively absorbed by Nx in 2022. The Lerna brand still exists but it's now a wrapper around Nx internals. If you're starting fresh, skip Lerna and pick Turborepo or Nx directly.
How does remote caching change CI economics?
Dramatically. A cold build that takes ten minutes can drop to under sixty seconds with a warm remote cache. For teams running fifty CI builds per day, that's eight hours of compute saved daily. The remote cache pays for itself within a week on most teams.
What if my team has both frontend and backend in the same monorepo?
Both tools handle it. The question is whether your backend services need orchestration with your frontend. If they share types or API contracts (typical with tRPC or a shared OpenAPI schema), the monorepo wins. If they're truly independent, polyrepo is fine and cleaner.
Is the configuration cost worth it for solo developers?
Usually no. Solo developers benefit more from polyrepo's simplicity unless they have three or more interconnected packages. The exception is when you're shipping an open-source library plus its docs site plus example apps in one repo, which is exactly the case Turborepo was designed for.