nx vs turbo vs lerna
Monorepo Tooling for JavaScript and TypeScript Projects
nxturbolernaSimilar Packages:
Monorepo Tooling for JavaScript and TypeScript Projects

lerna, nx, and turbo are all tools designed to manage monorepos — codebases that contain multiple packages or applications in a single repository. They help with tasks like dependency management, task orchestration, caching, and cross-project development workflows. While they share the goal of improving developer productivity in complex codebases, they differ significantly in architecture, scope, and philosophy.

Npm Package Weekly Downloads Trend
3 Years
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
nx7,935,31327,7089.95 MB7702 hours agoMIT
turbo6,951,24329,25334.9 kB1528 days agoMIT
lerna1,865,62736,0598.54 MB38515 days agoMIT

Monorepo Mastery: Lerna vs Nx vs Turbo Compared

Managing multiple projects in one repository used to mean endless scripts and manual coordination. Today, lerna, nx, and turbo offer structured solutions — but they solve different problems in different ways. Let’s cut through the noise and compare how each handles real-world engineering challenges.

📦 Core Philosophy: Package Manager vs Full Platform vs Task Runner

lerna started as a lightweight CLI to manage npm packages in a monorepo. It assumes you’re using npm workspaces (or its own linking system) and focuses on versioning, publishing, and running scripts across packages. It doesn’t care how you build your apps — just that they’re valid npm packages.

// lerna.json
{
  "version": "independent",
  "npmClient": "npm",
  "useWorkspaces": true
}

nx is a full development platform. It includes a powerful task orchestrator, dependency graph analysis, code generation, linting rules, and deep editor integration. It treats your monorepo as a unified system where apps, libs, and tools are first-class citizens with enforced relationships.

// nx.json
{
  "targetDefaults": {
    "build": {
      "dependsOn": ["^build"],
      "inputs": ["production", "^production"]
    }
  }
}

turbo is a high-performance task runner focused on speed and caching. It doesn’t manage dependencies or enforce project structure — it just runs your existing npm scripts faster by skipping redundant work and sharing caches across machines.

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

⚙️ Dependency Management: Workspaces vs Native vs None

All three assume you’re using npm workspaces, Yarn workspaces, or pnpm workspaces for dependency hoisting and linking. None replace your package manager.

  • lerna: Historically managed symlinks itself, but now recommends useWorkspaces: true to delegate to npm/Yarn/pnpm.
  • nx: Fully compatible with any workspace setup; uses it to resolve project relationships.
  • turbo: Agnostic — only reads package.json scripts and workspace topology.

✅ All three work best when you’ve already set up a modern workspace with your preferred package manager.

🏃 Task Execution: Script Runner vs Smart Orchestrator vs Parallel Cache Engine

Running Builds Across Projects

lerna runs npm scripts across packages using simple filtering:

# lerna: Run build in all packages that have a "build" script
lerna run build

# Only in packages that depend on "utils"
lerna run build --scope="*" --include-dependencies --since=main

nx uses a dependency-aware task graph. It knows which projects changed and which tasks depend on others:

# nx: Build only affected projects since main
nx affected:build

# Or build a specific project and its deps
nx build my-app

turbo runs tasks in topological order with content-aware caching:

# turbo: Run build across all packages with shared cache
turbo run build

# Only rebuild what changed based on file hashes
turbo run build --filter="./apps/*"

Code Example: Building a Frontend App That Depends on a Shared Lib

Assume this structure:

/packages
  /shared-utils
  /web-app

lerna requires you to ensure shared-utils is built before web-app, often via --include-dependencies:

lerna run build --scope=web-app --include-dependencies

nx automatically infers the dependency from imports or explicit tags and runs shared-utils:build first:

nx build web-app  # automatically builds shared-utils if needed

turbo uses the dependsOn: ["^build"] rule in turbo.json to enforce order:

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

Then:

turbo run build --filter=web-app...

🧠 Caching: Local Only vs Advanced Local + Remote vs Built-In Remote

lerna has no built-in caching. Every lerna run executes scripts unless you add external tooling.

nx offers computation caching based on source files, environment variables, and task inputs. Supports local disk and remote distributed caching (via Nx Cloud or self-hosted):

# Enable remote caching in nx.json
{
  "tasksRunnerOptions": {
    "default": {
      "runner": "nx/tasks-runners/default",
      "options": {
        "cacheableOperations": ["build", "test"],
        "remoteCache": {
          "url": "https://your-nx-cache.com"
        }
      }
    }
  }
}

turbo was built for remote caching from day one. It hashes inputs and uploads/downloads artifacts automatically when connected to Vercel or a custom endpoint:

# Login to enable remote caching
turbo login

# Now all runs share cache across team
turbo run build

🔍 Developer Experience: CLI Only vs IDE Integration vs Zero Config

lerna is CLI-only. No editor plugins, no graph visualization, no code generators.

nx ships with VS Code and WebStorm plugins, a graph visualizer (nx graph), and schematics for generating components, libs, and apps:

# Generate a new React lib with tests, storybook, etc.
nx g @nx/react:lib ui-components

turbo aims for zero-config adoption. Just add turbo.json and run turbo run. No generators, no IDE plugins — but integrates smoothly with existing tooling like Next.js or Vite.

🛠️ Use Case Fit: When to Reach for Which

Scenario 1: Open-Source Library Monorepo (e.g., Babel, Jest)

  • You publish many small npm packages.
  • Versioning and changelogs matter most.
  • Best choice: lerna
  • Why? Built for this exact workflow. lerna version and lerna publish handle independent or fixed versioning cleanly.
# Standard OSS release flow with lerna
lerna version --conventional-commits
lerna publish from-git

Scenario 2: Enterprise Application Suite (e.g., Admin Panel + Customer App + Shared APIs)

  • Multiple apps share UI libs, utils, and backend services.
  • Need strict code ownership, linting rules, and dependency constraints.
  • Best choice: nx
  • Why? Enforces architecture, prevents bad imports, and accelerates dev with generators and affected commands.
// nx.json: Enforce that "feature-x" can't import from "admin-only"
{
  "namedInputs": {
    "default": ["{projectRoot}/**/*"]
  },
  "targetDefaults": {
    "build": {
      "inputs": ["default", "^default"]
    }
  }
}

Scenario 3: Startup with Fast-Moving Team Using Modern Stacks (Next.js, SvelteKit, etc.)

  • Want CI to be 10x faster with minimal setup.
  • Already use npm workspaces and standard build scripts.
  • Best choice: turbo
  • Why? Drop-in speed boost with remote caching. No need to restructure your repo or learn new abstractions.
// Minimal turbo.json for a Next.js monorepo
{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "build": {
      "outputs": [".next/**", "!build/**"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}

🔄 Migration and Interoperability

  • lerna + nx: Nx can import an existing Lerna repo using nx init.
  • turbo + anything: Turbo works alongside Lerna or Nx — just add turbo.json and replace lerna run or nx run with turbo run for cached tasks.
  • Not recommended: Using Lerna’s legacy bootstrapping (lerna bootstrap) in new projects — stick to npm workspaces.

📊 Summary Table

Featurelernanxturbo
Primary FocusPackage publishingFull dev platformTask speed & caching
Caching❌ None✅ Local + remote✅ Local + remote (built-in)
Task IntelligenceBasic filteringDependency graph awareInput hashing + topological
IDE Integration✅ VS Code, WebStorm
Code Generation✅ Schematics
Remote Caching SetupN/ARequires configturbo login
Best ForOSS npm packagesLarge app suitesSpeed-focused teams

💡 Final Thought

These tools aren’t mutually exclusive — and you might even combine them. But start by asking:

  • Are you publishing packages? → lerna
  • Are you building complex apps with shared code? → nx
  • Do you just want faster builds with less config? → turbo

Pick the tool that matches your team’s biggest pain point today — not the one with the most features.

How to Choose: nx vs turbo vs lerna
  • nx:

    Choose nx if you’re building a large-scale application suite (e.g., multiple frontend apps sharing backend services and libraries) and need deep tooling for task orchestration, computation caching, dependency graph visualization, and editor integration. Nx excels when you want a batteries-included experience with first-class support for frameworks like React, Angular, and NestJS, along with strong project boundaries and code quality enforcement.

  • turbo:

    Choose turbo if you prioritize speed and simplicity in task execution and caching, especially in CI environments. Turbo is ideal for teams already using modern toolchains (like Vite, Next.js, or Remix) who want minimal configuration, fast incremental builds, and seamless remote caching without adopting a full framework ecosystem.

  • lerna:

    Choose lerna if you're maintaining a traditional package-based monorepo (like those common in open-source libraries) and need straightforward versioning, publishing, and npm workspace integration. It’s ideal when your primary needs are managing interdependent packages with conventional changelog-driven releases and you don’t require advanced build pipelines or deep IDE integrations.

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