nx vs turbo vs lerna vs @microsoft/rush
Monorepo Tooling for Modern JavaScript Projects
nxturbolerna@microsoft/rushSimilar Packages:
Monorepo Tooling for Modern JavaScript Projects

@microsoft/rush, lerna, nx, and turbo are all tools designed to manage JavaScript/TypeScript monorepos—codebases that contain multiple packages or applications in a single repository. They address challenges like dependency hoisting, cross-package linking, task orchestration, and build optimization. While they share overlapping goals, their architectures, philosophies, and feature sets differ significantly. Rush emphasizes strict dependency management and enterprise-scale workflows; Lerna pioneered the space with simple package publishing and linking; Nx provides deep project graph analysis and computation caching with strong support for full-stack development; Turbo (from Vercel) focuses on high-speed incremental builds and remote caching with minimal configuration.

Npm Package Weekly Downloads Trend
3 Years
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
nx6,442,14727,4899.84 MB7905 days agoMIT
turbo6,214,78329,08834.8 kB1545 days agoMIT
lerna1,450,24236,0478.54 MB3812 days agoMIT
@microsoft/rush638,1586,355465 kB968a month agoMIT

Monorepo Orchestration Deep Dive: Rush vs Lerna vs Nx vs Turbo

Managing a JavaScript monorepo isn’t just about putting multiple projects in one folder—it’s about solving hard problems: consistent dependencies, efficient builds, safe publishing, and developer velocity at scale. Let’s dissect how @microsoft/rush, lerna, nx, and turbo tackle these challenges.


Dependency Management: Hoisting, Lockfiles, and Consistency

@microsoft/rush uses its own install engine (wrapping PNPM by default) to enforce single-version policy: every package in the repo must use the same version of any given dependency. This eliminates subtle bugs from version skew but requires careful coordination during upgrades.

// rush.json
{
  "pnpmVersion": "8.7.0",
  "ensureConsistentVersions": true,
  "projects": [
    { "packageName": "@myorg/ui", "projectFolder": "packages/ui" },
    { "packageName": "@myorg/api", "projectFolder": "apps/api" }
  ]
}

lerna delegates entirely to the underlying package manager (npm/yarn/pnpm). It doesn’t enforce version consistency—each package can have its own node_modules tree unless you enable useWorkspaces. This flexibility often leads to diamond dependency issues in practice.

nx is agnostic—it works atop npm, Yarn, or PNPM workspaces. However, it provides dependency constraints via nx.json to enforce rules like “libs cannot depend on apps”:

// nx.json
{
  "targetDefaults": {
    "build": { "dependsOn": ["^build"] }
  },
  "dependencyConstraints": {
    "enforceBuildableLibDependency": true
  }
}

turbo assumes you’re using npm/Yarn/PNPM workspaces and doesn’t interfere with dependency resolution. It focuses purely on task execution, not dependency hygiene.


Task Orchestration: Running Builds, Tests, and Scripts

rush defines tasks via command-line.json, supporting phased execution and custom parameters:

// common/config/rush/command-line.json
{
  "commands": [
    {
      "commandKind": "bulk",
      "name": "build",
      "summary": "Build all projects",
      "safeForSimultaneousRushProcesses": true
    }
  ]
}

It runs tasks per-project but lacks deep awareness of what changed—you get parallelism, not intelligence.

lerna offers basic parallel/concurrent execution:

lerna run build --parallel

But it has no concept of task outputs or caching—every run rebuilds everything unless you script around it.

nx builds a project graph from source code imports and package.json dependencies. This enables nx affected:build to run only what’s needed:

# Only build projects affected by the last commit
nx affected:build --base=HEAD~1 --head=HEAD

Nx also supports computation caching—locally and via Nx Cloud—so identical inputs skip execution entirely.

turbo uses a pipeline definition to model task dependencies and cache outputs based on file hashes:

// turbo.json
{
  "pipeline": {
    "build": {
      "outputs": ["dist/**"],
      "dependsOn": ["^build"]
    },
    "test": {
      "outputs": [],
      "dependsOn": ["build"]
    }
  }
}

Run with turbo run build—it skips cached tasks and executes others in topological order.


Caching Strategy: Local vs Remote, Inputs vs Outputs

rush has no built-in caching. You’d need to layer in something like Azure Artifacts or custom scripts.

lerna also lacks caching—every task runs from scratch.

nx caches based on source files, environment variables, and task configuration. The cache includes terminal output and artifacts. With Nx Cloud, teams share a remote cache:

# Enable remote caching
nx connect-to-nx-cloud

turbo caches task outputs (defined in turbo.json) using content hashes of inputs (source files, env vars, global hash). Remote caching is built-in via Vercel’s infrastructure:

# Login to enable remote cache
npx turbo login

Both Nx and Turbo invalidate correctly on code changes—but Nx’s project graph gives it finer granularity (e.g., skipping tests for unchanged libs).


Publishing Workflows: Versioning and Release Safety

rush excels here with change files—developers describe changes via rush change, then rush version auto-bumps versions and updates changelogs. Publishing is atomic and auditable:

rush change --type minor --message "Add dark mode"
rush version
rush publish --include-all

lerna popularized lerna version and lerna publish, but its fixed/independent modes are error-prone without additional tooling. No built-in change tracking.

nx doesn’t handle publishing natively—you’d use nx release (experimental) or integrate with Changesets or manually script it.

turbo has no publishing features. It’s purely a build orchestrator.


Developer Experience and Ecosystem

rush demands upfront investment: config files live in common/config/rush, and you must adopt its conventions. Great for enterprises, overkill for small teams.

lerna feels familiar but dated—its simplicity is now a liability as monorepo needs evolve.

nx offers generators (nx g @nx/react:lib ui) and lint rules that understand your project graph. Plugins exist for every major framework, and the VS Code extension shows dependency visualizations.

turbo wins on zero-config adoption—add turbo.json and you’re off. But you trade configurability for speed; no code generators, no dependency linting.


Similarities: Shared Ground Among Monorepo Tools

Despite differences, all four tools converge on key principles:

1. Workspace-Aware Execution

Each understands that a monorepo contains multiple logical projects and can run scripts across them:

# Common pattern: run test in all packages
rush test          # Rush
lerna run test     # Lerna
nx run-many -t test # Nx
turbo run test     # Turbo

2. Parallelization

All support concurrent task execution to leverage multi-core machines:

# Example: build all projects in parallel
rush build --parallel
lerna run build --parallel
nx run-many -t build --parallel

3. Integration with Modern Package Managers

They assume you’re using npm/Yarn/PNPM workspaces under the hood (except Rush, which wraps PNPM directly).

4. Focus on Incremental Workflows

Even Lerna (via --since) tries to limit scope—though only Nx and Turbo do it robustly.


Summary: Key Differences

Feature@microsoft/rushlernanxturbo
Dependency PolicyEnforces single-versionNo enforcementConstraints via configNo enforcement
Task IntelligenceBasic parallelismBasic parallelismProject graph + affectedPipeline + file hashing
CachingNoneNoneLocal + remote (Nx Cloud)Local + remote (Vercel)
PublishingBuilt-in (change files)Built-in (basic)Experimental / manualNone
Code GenerationNoNoYes (via plugins)No
Best ForEnterprise-scale, strict controlLegacy repos, simple publishingFull-stack apps, DX-focusedSpeed-focused, minimal config

The Big Picture:

  • If you work at Microsoft-scale with compliance needs, Rush is unmatched.
  • Lerna is a historical artifact—avoid for new projects.
  • Nx is the Swiss Army knife: deep insights, rich plugins, and future-proof architecture.
  • Turbo is the drag racer: fastest out of the gate with least setup, but fewer safety rails.

Choose based on whether your bottleneck is correctness (Rush), velocity (Nx), or raw speed (Turbo).

How to Choose: nx vs turbo vs lerna vs @microsoft/rush
  • nx:

    Choose Nx when you need intelligent task orchestration powered by a fine-grained project graph, extensive plugin ecosystem (React, Angular, NestJS, etc.), and local/remote computation caching. Nx shines in full-stack monorepos with interdependent apps and libs, offering features like affected commands, code generation, and distributed task execution. Its deep integration with modern frameworks and developer ergonomics make it a strong choice for teams prioritizing DX and long-term maintainability.

  • turbo:

    Opt for turbo when your top priority is build speed through incremental execution and remote caching with minimal setup. Turbo’s zero-config approach (especially with Turborepo) works well for teams already using npm or Yarn workspaces and wanting fast CI without complex pipeline definitions. It’s particularly effective in Vercel-hosted environments but lacks built-in code generation, dependency constraints, or deep framework integrations found in Nx.

  • lerna:

    Lerna is best suited for smaller or legacy monorepos where the primary needs are basic package linking and versioned publishing. While it once dominated the space, its core functionality has been largely superseded by more modern tools. Avoid using Lerna for new projects unless you specifically require its lightweight publishing model and don’t need advanced features like computation caching or deep task orchestration. For most greenfield efforts, consider Nx or Turbo instead.

  • @microsoft/rush:

    Choose @microsoft/rush if you're operating at enterprise scale with strict requirements around dependency consistency, deterministic installs, and CI reproducibility. Rush enforces a single version policy for dependencies across projects and integrates tightly with PNPM via its own installer wrapper. It’s ideal for large teams needing auditability, change logs, and safe publishing workflows—but be prepared for higher configuration overhead and less flexibility in toolchain choices.

README for nx

Nx - Smart Repos · Fast Builds

CircleCI License NPM Version Semantic Release Commitizen friendly Join the chat at https://gitter.im/nrwl-nx/community Join us on the Official Nx Discord Server


Nx: Smart Repos · Fast Builds

Get to green PRs in half the time. Nx optimizes your builds, scales your CI, and fixes failed PRs. Built for developers and AI agents.

Getting Started

Creating an Nx Workspace

Using npx

npx create-nx-workspace

Using npm init

npm init nx-workspace

Using yarn create

yarn create nx-workspace

Adding Nx to an Existing Repository

Run:

npx nx@latest init

Documentation & Resources

Nx - Smart Repos · Fast Builds