Overview
Use Turborepo when the monorepo is under 20 packages, the team trusts npm or pnpm workspaces, and the goal is “make CI fast.” Use Nx when the repo holds 30-plus packages, mixes frameworks (Next.js, Nest, React Native, libraries), or needs a project graph, code generators, and enforced module boundaries. Turborepo wins on simplicity; Nx wins on scope. See monorepo for the underlying monorepo rules.
When Turborepo wins
Turborepo is the right pick for small to medium TypeScript and JavaScript monorepos where caching and parallel task execution are the only real needs.
- Setup: drop a
turbo.jsonwith a pipeline definition; tasks likebuild,lint, andtestparallelize and cache without further config. Most repos are productive in an afternoon. - Local cache hits work out of the box; remote cache via Vercel Remote Cache or self-hosted is a flag, not a plugin install.
- Filters:
turbo run build --filter=./apps/webruns only what changed. The CLI matches what mental model developers already have. - No project graph to learn. Tasks, inputs, outputs, and dependencies are the entire vocabulary.
- Works with whatever package manager you already use; pnpm workspaces remain the source of truth.
- Small team threshold: under 10 engineers, the Nx tax usually outweighs the win.
When Nx wins
Nx is the right pick once the repo grows past what Turborepo’s flat task graph covers, or when the team wants enforced architecture.
- Project graph:
nx graphis a real dependency graph the team can read, search, and lint against. Module boundary rules (@nx/enforce-module-boundaries) prevent forbidden imports at lint time. - Generators and executors: scaffold a new library or app with the framework’s conventions baked in. Saves real time once the repo has 20-plus packages.
- Affected commands:
nx affected -t testruns only what changed sincemain; the dependency graph is more accurate than Turborepo’s input-hashing approach for complex repos. - Plugin ecosystem: official plugins for Next.js, Nest, React Native, Storybook, Cypress, Playwright, Detox, Expo, Vite, Webpack. Each plugin teaches Nx how the tool builds and tests.
- Migrations:
nx migrateupgrades plugin versions and rewrites configs across the whole workspace. At 50-plus packages, this saves engineer-weeks per major upgrade. - Distributed task execution (Nx Cloud) parallelizes a CI job across multiple machines automatically. Turborepo Remote Cache is faster on cold builds but does not split a single job.
Trade-offs at a glance
| Dimension | Turborepo | Nx |
|---|---|---|
| Config | One turbo.json | nx.json plus per-project configs |
| Mental model | Pipeline of tasks | Project graph plus executors and generators |
| Local cache | Default | Default |
| Remote cache | Vercel Remote Cache or self-hosted | Nx Cloud or self-hosted |
| Affected detection | Input hashing | Graph-based |
| Generators | None | Full scaffolding system |
| Module boundaries | Manual via ESLint config | First-class lint rule |
| Plugins | Minimal | Large official catalog |
| Distributed CI | No (single-job cache speedup only) | Yes (Nx Agents) |
| Learning curve | One day | One to two weeks |
| Lock-in shape | Low; remove turbo.json and continue | Higher; generators leave Nx-shaped configs |
| Sweet spot | 5 to 25 packages | 25 to 500-plus packages |
Migration cost
Turborepo-to-Nx is the common direction when a repo outgrows the flat task graph. The reverse is rare and usually mid-rewrite.
- Turborepo to Nx: keep pnpm workspaces, install Nx, run
nx init, and let it generateproject.jsonper package. Portturbo.jsonpipeline to Nx targets. Plan one to two engineer-weeks for a 30-package repo plus another to adopt the lint rules. - Nx to Turborepo: only worth it if Nx adds friction without benefit. Strip executors back to plain npm scripts and write
turbo.jsonby hand. Plan one engineer-week for the conversion plus follow-up to remove Nx-specific imports. - Cheaper path: stay on Turborepo, adopt one Nx-style convention at a time (project graph linting via dependency-cruiser, generator scripts in a
tools/directory).
Recommendation
- New monorepo with 1 to 3 apps and a handful of packages: Turborepo. Set up in an hour; do not over-engineer.
- Existing pnpm workspace that is slow in CI: Turborepo with Remote Cache. Usually a one-day win.
- Repo crossing 30 packages, multiple frameworks, or three-plus teams: Nx. The plugin and graph value compounds.
- Repo with mobile (React Native, Expo) plus web plus backend: Nx; the plugins matter.
- Team of one to three engineers: Turborepo. Nx’s tax does not pay off at this size.
- Already on Nx with no friction: stay. The switch buys little.
- See monorepo-vs-polyrepo for the upstream “do I want a monorepo at all” decision.