Monorepo Tooling 2026: Nx vs Turborepo vs Bazel vs Lerna
Watch a repo team turn architecture context into a reviewed change.
The sample scopes the work, gathers repository evidence, proposes a patch, checks it, and pauses for approval.
A monorepo stores multiple projects, libraries, and services in a single repository. Google, Meta, Microsoft, and Uber all run massive monorepos — but the pattern works at every scale.
Monorepo vs Polyrepo#
Monorepo Polyrepo
┌─────────────────────┐ ┌──────┐ ┌──────┐ ┌──────┐
│ apps/ │ │ repo │ │ repo │ │ repo │
│ web/ │ │ A │ │ B │ │ C │
│ api/ │ └──────┘ └──────┘ └──────┘
│ packages/ │ each has own CI, deps,
│ ui-lib/ │ versioning, and review
│ shared-utils/ │
│ .github/CODEOWNERS │
└─────────────────────┘
Monorepo Advantages#
- Atomic changes — refactor a shared library and every consumer in one PR
- Single source of truth — no version drift between packages
- Code reuse — shared utilities, types, and configs live alongside apps
- Unified CI/CD — one pipeline, one set of checks
- Easier onboarding — clone once, see everything
Polyrepo Advantages#
- Isolation — a broken build in repo A never blocks repo B
- Granular permissions — easier access control per repository
- Simpler at small scale — no monorepo tooling overhead
- Independent deploy cadence — teams ship on their own schedule
Monorepo Tooling Comparison#
| Tool | Language | Build Cache | Remote Cache | Task Graph | Plugin Ecosystem |
|---|---|---|---|---|---|
| Nx | JS/TS (+ others) | Yes | Yes (Nx Cloud) | Yes | Rich |
| Turborepo | JS/TS | Yes | Yes (Vercel) | Yes | Minimal |
| Bazel | Any | Yes | Yes | Yes | Extensive |
| Lerna | JS/TS | Via Nx | Via Nx | Limited | Moderate |
| Rush | JS/TS | Yes | Yes | Yes | Moderate |
| Pants | Python/Go/Java | Yes | Yes | Yes | Growing |
Nx#
Nx provides computation caching, affected-only execution, and a rich plugin system for React, Angular, Node, and more.
# Create an Nx workspace
npx create-nx-workspace@latest my-org
# Run only affected projects
npx nx affected --target=build
# Visualize the dependency graph
npx nx graph
Turborepo#
Turborepo focuses on speed and simplicity. It layers on top of existing package managers (npm, pnpm, yarn).
# turbo.json
{
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"test": {
"dependsOn": ["build"]
},
"lint": {}
}
}
Bazel#
Bazel handles any language and scales to millions of lines of code. It uses hermetic builds and content-addressable caching.
# BUILD file
ts_library(
name = "shared-utils",
srcs = glob(["src/**/*.ts"]),
deps = ["//packages/types"],
)
Dependency Management#
Internal Dependencies#
Structure packages so they reference each other through the workspace protocol:
{
"name": "@org/web-app",
"dependencies": {
"@org/ui-lib": "workspace:*",
"@org/shared-utils": "workspace:*"
}
}
Version Policies#
- Fixed/locked — all packages share one version number (simpler)
- Independent — each package versions independently (more flexible)
- Hybrid — groups of related packages lock together
Dependency Graph Visualization#
@org/web-app
├── @org/ui-lib
│ └── @org/design-tokens
├── @org/shared-utils
└── @org/api-client
└── @org/shared-utils (deduplicated)
@org/api-server
├── @org/shared-utils
└── @org/db-models
Tools like nx graph or turbo run build --graph render interactive dependency graphs so you can spot circular dependencies early.
Build Caching#
Build caching is the single biggest performance win in a monorepo.
How It Works#
1. Hash inputs (source files + deps + config + env)
2. Check cache for matching hash
3. Cache HIT → restore outputs instantly
4. Cache MISS → run task, store outputs with hash
Local vs Remote Cache#
- Local cache — stored on the developer machine (
node_modules/.cache) - Remote cache — shared across the team and CI (Nx Cloud, Vercel Remote Cache, custom S3 bucket)
Developer A runs build → uploads artifacts to remote cache
Developer B runs same build → downloads cached result (seconds vs minutes)
CI runs same build → cache hit (no rebuild)
Cache Invalidation#
Caches invalidate automatically when any input changes:
- Source file modified
- Dependency version bumped
- Environment variable changed
- Build config updated
CI/CD for Monorepos#
Affected-Only Builds#
Never rebuild everything. Run tasks only for packages affected by the current change:
# GitHub Actions example
jobs:
build:
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # full history for diff
- run: npx nx affected --target=build --base=origin/main
- run: npx nx affected --target=test --base=origin/main
Parallel Execution#
Monorepo tools understand the task graph and run independent tasks in parallel:
lint ──────────┐
build:ui-lib ──┤
build:utils ───┤──→ build:web-app ──→ deploy:web
build:api ─────┘──→ deploy:api
Selective Deploys#
Only deploy services whose code actually changed:
deploy-web:
if: contains(needs.changes.outputs.packages, 'web-app')
steps:
- run: npx nx build web-app --production
- run: deploy-to-vercel
Code Ownership with CODEOWNERS#
The CODEOWNERS file maps directories to responsible teams:
# .github/CODEOWNERS
# Platform team owns infrastructure
/infra/ @org/platform-team
/.github/ @org/platform-team
# Frontend team owns UI packages
/apps/web/ @org/frontend-team
/packages/ui-lib/ @org/frontend-team
# Backend team owns API
/apps/api/ @org/backend-team
/packages/db-models/ @org/backend-team
# Shared code requires two approvals
/packages/shared-utils/ @org/frontend-team @org/backend-team
This enforces review gates — PRs touching /apps/api/ automatically request review from the backend team.
When to Choose a Monorepo#
Choose Monorepo When#
- Teams share libraries, types, or configs frequently
- You want atomic cross-project refactors
- Consistent tooling and standards matter
- You have (or will invest in) CI/CD infrastructure
- Codebase is under ~10 million lines (or you use Bazel)
Choose Polyrepo When#
- Teams are fully independent with no shared code
- Projects use completely different tech stacks
- Strict access control is required per project
- You lack CI/CD capacity for monorepo tooling
- Regulatory requirements mandate repository isolation
Hybrid Approach#
Many organizations use a hybrid: a monorepo for tightly coupled services and separate repos for truly independent projects.
monorepo/ # core platform
apps/web
apps/api
packages/shared
repo: mobile-app # different release cycle
repo: data-pipeline # different team, different stack
repo: ml-models # heavy binary assets
Common Pitfalls#
- No build caching — monorepo CI without caching is painfully slow
- Circular dependencies — use lint rules and graph visualization to prevent them
- Giant PRs — atomic changes are powerful but reviewers need sane PR sizes
- Missing CODEOWNERS — without ownership, shared code rots
- Ignoring affected commands — running all tests on every PR wastes CI minutes
Quick-Start Checklist#
[ ] Pick a tool (Nx for full-featured, Turborepo for simplicity)
[ ] Set up workspace with apps/ and packages/ directories
[ ] Configure build caching (local first, then remote)
[ ] Add CODEOWNERS for every top-level directory
[ ] Set up affected-only CI builds
[ ] Document package creation and dependency conventions
[ ] Add dependency graph visualization to onboarding
Explore the full architecture series on Codelit.io. This is article #346 in our growing library of software architecture and system design guides.
Watch a repo team turn architecture context into a reviewed change.
The sample scopes the work, gathers repository evidence, proposes a patch, checks it, and pauses for approval.
Try these templates
Netflix Video Streaming Architecture
Global video streaming platform with adaptive bitrate, CDN distribution, and recommendation engine.
10 componentsGitHub-like CI/CD Pipeline
Continuous integration and deployment system with parallel jobs, artifact caching, and environment management.
9 componentsSearch Engine Architecture
Web-scale search with crawling, indexing, ranking, and sub-second query serving.
8 componentsContinue learning
Go deeper on infrastructure and delivery
As an Amazon Associate I earn from qualifying purchases. Codelit may receive a commission at no extra cost to you.
The DevOps Handbook
Gene Kim, Jez Humble · 2021
Case studies from Etsy, Amazon, and Target on rewiring deployment pipelines and org structure.
Terraform: Up and Running
Yevgeniy Brikman · 2022
Working modules, state locking, and testing patterns for teams past the single-workspace stage.
4.6 (260)Fundamentals of Software Architecture
Mark Richards, Neal Ford · 2025
Scores eight architecture styles against the same characteristics, so trade-offs are side by side.
Enterprise Integration Patterns
Gregor Hohpe, Bobby Woolf · 2003
A catalog of 65 messaging patterns with diagrams - the vocabulary queue designs still use today.
4.6 (581)