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.json with a pipeline definition; tasks like build, lint, and test parallelize 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/web runs 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 graph is 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 test runs only what changed since main; 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 migrate upgrades 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

DimensionTurborepoNx
ConfigOne turbo.jsonnx.json plus per-project configs
Mental modelPipeline of tasksProject graph plus executors and generators
Local cacheDefaultDefault
Remote cacheVercel Remote Cache or self-hostedNx Cloud or self-hosted
Affected detectionInput hashingGraph-based
GeneratorsNoneFull scaffolding system
Module boundariesManual via ESLint configFirst-class lint rule
PluginsMinimalLarge official catalog
Distributed CINo (single-job cache speedup only)Yes (Nx Agents)
Learning curveOne dayOne to two weeks
Lock-in shapeLow; remove turbo.json and continueHigher; generators leave Nx-shaped configs
Sweet spot5 to 25 packages25 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 generate project.json per package. Port turbo.json pipeline 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.json by 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.