Monorepos make sense for many teams. Shared code, atomic commits across projects, unified CI/CD, consistent tooling — the benefits are real. But without proper tooling, a monorepo becomes a slow, tangled mess. The build takes forever, CI runs everything on every change, and developers spend more time waiting than coding.
Three tools dominate the monorepo space: Nx, Turborepo, and Bazel. They solve the same core problem — making monorepos fast and manageable — but they approach it differently.
The Core Problem These Tools Solve
In a monorepo with 10 projects, changing one file should not trigger builds and tests for all 10. These tools provide:
- Task orchestration: Run builds, tests, and lints in the right order based on dependencies
- Caching: If nothing changed in a project, reuse the last build output instead of rebuilding
- Affected detection: Determine which projects are impacted by a code change and only run tasks for those
- Parallelism: Run independent tasks simultaneously
Nx
Nx started in the Angular ecosystem but has evolved into a general-purpose monorepo tool that works with any language or framework. It is the most feature-rich option and provides the most out-of-the-box support.
Strengths
- Rich plugin ecosystem: Official plugins for React, Angular, Vue, Node.js, Go, Rust, and more. Each plugin provides generators (scaffolding), executors (task runners), and best-practice configurations.
- Affected command:
nx affected --target=testdetermines which projects are affected by your changes and only runs tests for those projects. This is based on the project dependency graph. - Computation caching: Local and remote caching. If a teammate already built a project with the same inputs, you get their cached result instead of rebuilding.
- Nx Cloud: Remote caching and distributed task execution. According to Nx, this can reduce CI times by 50-70% for large monorepos.
- Interactive project graph: Visualize your entire monorepo's dependency graph in the browser with
nx graph. - Code generators: Scaffold new projects, libraries, and components with consistent structure.
Limitations
- The plugin system adds complexity — you are adopting Nx's opinions about project structure
- Configuration can become verbose in large workspaces
- Nx-specific concepts (executors, generators) have a learning curve
Configuration
Nx uses nx.json for workspace-level configuration and project.json for per-project settings. It also supports package.json-based configuration for less opinionated setups.
Best for: Teams that want a batteries-included solution with strong conventions and framework-specific tooling. Particularly strong for JavaScript/TypeScript monorepos.
Pricing: Open source. Nx Cloud free tier available. Paid plans for teams start at $99/month.
Turborepo
Turborepo (now part of Vercel) takes a minimalist approach. Where Nx is a full-featured toolkit, Turborepo is a focused task runner that layers onto your existing package.json scripts.
Strengths
- Minimal setup: Add
turbo.json, define your pipeline, and you are running. It works with your existing npm/yarn/pnpm scripts — no need to learn a new task API. - Pipeline definition: Define task dependencies declaratively. "Build depends on the build of its dependencies" is expressed simply in
turbo.json. - Caching: Local caching out of the box. Remote caching with Vercel or self-hosted options.
- Incremental adoption: You can add Turborepo to an existing monorepo without restructuring anything. It respects your existing project structure.
- Pruning:
turbo prunegenerates a sparse monorepo containing only the packages needed for a specific app — useful for Docker builds.
Limitations
- JavaScript/TypeScript only: Turborepo is designed for the Node.js ecosystem. It uses
package.jsonworkspaces as its project model. - Fewer built-in features: No code generators, no framework-specific plugins. (Note: Turborepo v2 added built-in project graph visualization via
turbo graph.) - Less opinionated: This is a strength for some and a weakness for others. Turborepo does not tell you how to structure your monorepo.
Configuration
A turbo.json file defines your task pipeline. That is essentially the only Turborepo-specific configuration.
Turborepo v2 (released early 2026) added built-in project graph visualization with turbo graph, improved task filtering, and first-party support for self-hosted remote caching without Vercel. The Rust rewrite of the core engine is now complete.
Best for: JavaScript/TypeScript teams that want fast caching and task orchestration with minimal configuration and no opinions about project structure.
Pricing: Open source. Remote caching free with Vercel account. Self-hosted caching available.
Bazel
Bazel is Google's open-source build system, originally built to manage Google's massive internal monorepo. It is the most powerful option but also the most complex.
Strengths
- Language agnostic: Build Java, C++, Go, Python, JavaScript, Rust, and virtually any other language in the same monorepo with the same tool.
- Hermeticity: Builds are hermetic — they do not depend on anything outside the declared inputs. This means builds are perfectly reproducible regardless of the machine running them.
- Remote execution: Distribute build tasks across a cluster of machines. For large codebases, this is transformative.
- Fine-grained caching: Caching operates at the individual action level, not the project level. A single changed file invalidates only the specific build steps it affects.
- Scalability: Proven at Google-scale (billions of lines of code). If your monorepo will eventually be very large, Bazel will not be the bottleneck.
Limitations
- Steep learning curve: Starlark (Bazel's configuration language) is powerful but unfamiliar. Writing BUILD files requires understanding Bazel's model.
- Ecosystem investment: Many third-party tools and plugins assume standard build tools (npm, Maven, Gradle). Bazel integration requires rules packages and sometimes custom rules.
- Overhead for small teams: The setup cost is significant. For monorepos with fewer than 10 projects, Bazel is often overkill.
- Community vs. enterprise: The open-source community is smaller than Nx or Turborepo. Enterprise support is through third parties.
Configuration
BUILD files define targets and dependencies using Starlark. WORKSPACE files (or the newer MODULE.bazel) declare external dependencies. Rules packages provide language-specific build logic.
Best for: Large engineering organizations with polyglot codebases that need hermetic, reproducible builds at scale.
Pricing: Open source. Remote execution infrastructure costs vary (self-hosted or services like BuildBuddy).
Head-to-Head Comparison
| Feature | Nx | Turborepo | Bazel | Moon |
|---|---|---|---|---|
| Setup complexity | Medium | Low | High | Low |
| Language support | JS/TS primary, others via plugins | JS/TS only | Any language | JS/TS (Rust-powered) |
| Caching | Local + remote | Local + remote | Local + remote | Local + remote |
| Affected detection | Yes | Yes | Yes | Yes |
| Code generators | Yes | No | No | No |
| Framework plugins | Extensive | None | Rules packages | None |
| Remote execution | Via Nx Cloud | No | Yes | No |
| Learning curve | Medium | Low | High | Low |
| Best scale | Small to large | Small to medium | Medium to massive | Small to medium |
Decision Guide
Choose Nx if:
- You are building a JavaScript/TypeScript monorepo
- You want conventions and best practices built in
- You value code generation and framework-specific tooling
- You want a project graph visualization
Choose Turborepo if:
- You want the simplest possible setup
- You already have a working monorepo and want to add caching
- You use Vercel for deployment
- You prefer minimal tooling opinions
Choose Bazel if:
- You have a polyglot codebase (multiple languages)
- You need hermetic, reproducible builds
- You are building at large scale (50+ projects, multiple teams)
- You can invest in the setup and learning curve
What About Lerna?
Lerna was the original JavaScript monorepo tool but is now maintained by the Nx team. It handles versioning and publishing for npm packages but delegates build orchestration to Nx. If you need npm package publishing from a monorepo, Lerna + Nx is a solid combination.
What's New in 2026
Turborepo v2 landed in early 2026 with significant improvements: a built-in project graph visualization (turbo graph), improved task filtering, and first-party support for self-hosted remote caching without Vercel. The Rust rewrite of the core engine is now complete, delivering measurably faster task scheduling.
Nx 20 introduced Crystal plugins — zero-configuration project inference that automatically detects project structure without project.json files. The new Nx Agents feature distributes CI tasks across multiple machines with automatic load balancing.
Moon emerged as a serious contender. Built in Rust, it focuses on developer experience with automatic dependency installation, integrated toolchain management, and a task runner that competes with Turborepo on speed. Worth evaluating for JS/TS teams starting fresh.
Bazel 8 (released late 2025) simplified the external dependency model with Bzlmod, making initial setup less painful. The new Starlark debugger also reduces the learning curve for writing custom rules.
The Bottom Line
For most JavaScript/TypeScript teams, the choice comes down to Nx vs Turborepo. If you want batteries-included with conventions, choose Nx. If you want minimal configuration with maximum flexibility, choose Turborepo. Bazel is the right choice only when you genuinely need its polyglot support and hermetic build guarantees — and when you can invest in the learning curve. Start with the simplest tool that meets your requirements and migrate only if you outgrow it.
Frequently Asked Questions
What is a monorepo and why would I use one?
A monorepo is a single repository containing multiple projects, libraries, or services. Teams use monorepos for shared code reuse, atomic commits across projects, unified CI/CD pipelines, and consistent tooling. Without proper build tools like Nx, Turborepo, or Bazel, monorepos become slow and hard to manage.
Should I choose Nx or Turborepo for a JavaScript monorepo?
Choose Nx if you want batteries-included tooling with code generators, framework plugins, and strong conventions. Choose Turborepo if you want minimal configuration that layers onto your existing package.json scripts. Turborepo is simpler to adopt; Nx is more feature-rich.
When should I use Bazel instead of Nx or Turborepo?
Use Bazel when you have a polyglot codebase (multiple languages like Java, Go, C++, and Python in one repo), need hermetic reproducible builds, or are operating at very large scale (50+ projects, multiple teams). For JavaScript/TypeScript-only monorepos, Nx or Turborepo are simpler choices.
Is Lerna still relevant in 2026?
Lerna is now maintained by the Nx team and focuses on npm package versioning and publishing. It delegates build orchestration to Nx. If you need to publish multiple npm packages from a monorepo, Lerna + Nx is a solid combination, but Lerna alone is no longer a complete monorepo solution.
What is Moon and how does it compare to Turborepo?
Moon is a Rust-built monorepo tool that focuses on developer experience with automatic dependency installation, integrated toolchain management, and fast task running. It competes with Turborepo on speed and simplicity. Moon is worth evaluating for JS/TS teams starting a new monorepo in 2026.
Recommended Reading & Gear
Scale your codebase with confidence:
- Software Engineering at Google by Titus Winters, Tom Manshreck & Hyrum Wright — how Google manages monorepos at planetary scale, including the build philosophy behind Bazel
- Monolith to Microservices by Sam Newman — practical patterns for decomposing codebases that inform when a monorepo makes sense
- Apple Mac Mini M4 — fast local builds for monorepo development with Nx and Turborepo at a fraction of cloud CI costs