Migrating from Turborepo to Nx

Already know you want to migrate?

Jump to:

Spoiler alert: The diff is tiny! Nx is a superset of Turborepo, so it can already do everything Turborepo can do without any extra configuration. (learn more about it in our free video course)

1.gitignore | 3 +++ # Ignore the Nx cache 2package.json | 1 + # Add the "nx" package 3package-lock.json | 4nx.json | # Equivalent to turbo.json 5

Why Migrate to Nx?

1. Superior Performance through Smarter Computation Caching

Nx is significantly faster than Turborepo, with open-source benchmarks showing more then 7x better performance in large monorepos. This is publicly verifiable here: large-monorepo benchmark.

The performance difference is particularly noticeable in larger, real-world monorepos, such as the one used in the benchmark.

nx and turbo benchmark

This isn't just about raw speed - Nx's approach to file restoration means it's both faster and more reliable, especially when working with tools that watch files.

2. Fast CI

Just like Turborepo, Nx provides FREE remote caching to small teams, both self-hosted and via its own cloud (Vercel in the case of Turborepo, Nx Cloud in the case of Nx). And just like Turborepo, Nx provides paid plans for larger, more sophisticated teams that need a higher level of service. For self-hosted remote caching, small teams can apply for FREE Nx Powerpack License here: https://nx.dev/powerpack

However, unlike Turborepo, Nx's CI solution (Nx Cloud) goes way beyond just locating a shared cache on a server somewhere.

Nx Cloud allows you to ship updates to your users faster and with more confidence than ever before thanks to:

  • Intelligently distributing your tasks across multiple machines without any manual "binning" configuration. Nx knows your workspace so let it decide what should run in what order.
  • File artifacts automatically collected and distributed
  • Built in support for versioning, changelog generation and publishing via Nx Release
  • Finally solving the pain of long-running, flaky e2e tests by:

This is crucial for scaling large monorepos, as distributed task execution has a significantly higher impact on scalability than computation caching alone. You can scale without caching, but you cannot scale without distribution.

3. Supports you all the way from vanilla package manager workspaces through to advanced Enterprise Monorepos

Nx works effortlessly with zero plugins with industry standard package manager workspaces from npm, yarn, pnpm and bun. Turborepo also works with these, but that's where it starts and ends.

Nx additionally works with any programming language, framework and tooling. The core of Nx is written in Rust for speed and TypeScript for extensibility, with a first-class plugin API for both task execution and project/dependency graph analysis.

This means that you do not need to add package.json files for languages like Rust, Java, Go, .NET, etc. that do not require them, and instead can install their respective Nx plugins.

Turborepo forces you to manually annotated your non-JavaScript packages, Nx understands it all through its first-class plugins, making it suitable for everything from open-source JavaScript tools with a handful of npm packages through to the largest enterprise-grade polyglot/multi-languages monorepos.

4. Superior Developer Experience

Rich Visualization

Being able to visually explore your workspace is crucial for large monorepos:

  • Nx: Rich, interactive visualizer, both locally via the nx graph CLI and for every pull request via Nx Cloud. (More in the docs)
  • Turborepo: Basic graphviz image export

IDE/Developer Tools

  • Nx: provides powerful VSCode and WebStorm/IntelliJ extensions with nearly 2 million installations. Run tasks, code generators, the graph visualizer, interact with Nx Cloud CI runs and more.
  • Turborepo: provides basic LSP support

5. Plugin System and Organizational Scaling

Nx is like the VSCode of build tools. Just as VSCode provides a core experience that can be enhanced with extensions for Git, Docker, MongoDB etc., Nx offers:

  • Core functionality that works out of the box
  • Rich plugin ecosystem for enhanced capabilities
  • Community plugins for additional tools and frameworks
  • Custom plugin development for organization-specific needs

This plugin system helps teams scale organizationally by:

  • Enabling consistent task execution across all projects
  • Automating large-scale refactorings
  • Providing tools to analyze cache misses
  • Supporting visibility constraints

6. Enterprise-Ready Features

  • Conformance rules for consistently enforcing best practices across your organization
  • On-premise and single-tenant Nx Cloud options
  • Distributed task execution (similar to Google's Bazel)
  • Advanced GitHub integration
  • Comprehensive analytics and insights
  • Module boundary rules essential for multi-team monorepos

7. Thriving Community

Nx has been battle-tested since 2016:

  • ~5 million downloads per week
  • Nearly 2 million unique Nx Console installations
  • Rich ecosystem of third-party plugins, many with millions of downloads in their own right
  • Used by over half of Fortune 500 companies in production

8. Incremental Adoption

Nx can be added to a repo with almost no friction. You can incrementally enable plugins and supporting features that are not available with Turborepo.

Here are some examples:

Easy Automated Migration Example

The simplest way to understand the concepts is to see a basic migration example.

  1. Let's create a new Turborepo workspace using the recommended create-turbo command:

โฏ

npx create-turbo@latest

  1. Once that is finished, literally all we need to do make it a valid Nx workspace is run nx init:

โฏ

npx nx@latest init

That's it! As you can see, the diff is tiny:

1.gitignore | 3 +++ # Ignore the Nx cache 2package.json | 1 + # Add the "nx" package 3package-lock.json | 4nx.json | # Equivalent to turbo.json 5
  • An nx.json file that is equivalent to the turbo.json file was added
  • The package.json file was updated to add the nx dev dependency (and the package-lock.json was updated accordingly)
  • The .gitignore entry for the Nx cache was added automatically

It's important to remember that Nx is a superset of Turborepo, it can do everything Turborepo can do and much more, so there is absolutely no special configuration needed for Nx, it just works on the Turborepo workspace.

Example: Basic Configuration Comparison

To help with understanding the new nx.json file, let's compare it to the turbo.json file:

1{ 2 "$schema": "https://turbo.build/schema.json", 3 // Nx will automatically use an appropriate terminal output style for the tasks you run 4 "ui": "tui", 5 "tasks": { 6 "build": { 7 // This syntax of build depending on the build of its dependencies using ^ is the same 8 // in Nx 9 "dependsOn": ["^build"], 10 // Inputs and outputs are in Turborepo are relative to a particular package, whereas in Nx they are consistently from the workspace root and it therefore has {projectRoot} and {projectName} helpers 11 "inputs": ["$TURBO_DEFAULT$", ".env*"], 12 "outputs": [".next/**", "!.next/cache/**"] 13 }, 14 "lint": { 15 // Turborepo tasks are assumed to be cacheable by default, so there is no recognizable configuration here. In Nx, the "cache" value is clearly set to true. 16 "dependsOn": ["^lint"] 17 }, 18 "check-types": { 19 "dependsOn": ["^check-types"] 20 }, 21 "dev": { 22 "cache": false, 23 // Nx has a powerful "continuous" setting for tasks in beta which even works across 24 // multiple machines. This is going to be generally available in Nx 21 and it will be a 25 // superset of Turborepo's "persistent" setting. 26 "persistent": true 27 } 28 } 29} 30

After running nx init, you'll automatically have an equivalent nx.json:

1{ 2 "$schema": "./node_modules/nx/schemas/nx-schema.json", 3 "targetDefaults": { 4 "build": { 5 "dependsOn": ["^build"], 6 "inputs": ["{projectRoot}/**/*", "{projectRoot}/.env*"], 7 "outputs": ["{projectRoot}/.next/**", "!{projectRoot}/.next/cache/**"], 8 "cache": true 9 }, 10 "lint": { 11 "dependsOn": ["^lint"], 12 "cache": true 13 }, 14 "check-types": { 15 "dependsOn": ["^check-types"], 16 "cache": true 17 }, 18 "dev": { 19 "cache": false 20 } 21 } 22} 23

Configuration Migration Guide

Most settings in the old turbo.json file can be converted directly into nx.json equivalents. Here's how to map each configuration property:

Global Configuration

Turborepo PropertyNx Equivalent
cacheDirSet in cacheDirectory
daemonUse NX_DAEMON=false or set useDaemonProcess: false in nx.json
envModeNx core does not block any environment variables. See React and Angular guides
globalDependenciesAdd to the sharedGlobals namedInput
globalEnvAdd to the sharedGlobals namedInput as an env input
globalPassThroughEnvN/A. See Defining Environment Variables
remoteCacheSee Nx Replay
uiNx will intelligently pick the most appropriate terminal output style, but it can be overridden with --output-style

Task Configuration

Turborepo PropertyNx Equivalent
extendsN/A. Projects always extend targetDefaults from nx.json
dependsOnSame syntax
envDefine env inputs
passThroughEnvN/A. See Defining Environment Variables
outputsSimilar syntax
cacheSimilar syntax
inputsSimilar syntax
outputLogsUse --output-style
persistentNx has a powerful "continuous" setting for tasks in beta which even works across multiple machines. This is going to be generally available in Nx 21 and it will be a superset of Turborepo's "persistent" setting.
interactiveAll "continuous" tasks (coming in Nx 21) are intelligently and automatically interactive.

Command Equivalents

Here's how Turborepo commands map to Nx:

Turborepo CommandNx Equivalent
turbo run test lint buildnx run-many -t test lint build
--cache-dirSet in nx.json under cacheDirectory
--concurrency--parallel
--continueUse --nx-bail with the inverse value
--cpuprofileUse NX_PROFILE=profile.json
--cwdAvailable in run-commands executor
--daemonUse NX_DAEMON=false or set useDaemonProcess: false
--dry-runN/A. Nx has --dry-run for nx generate but not for running tasks
--env-modeSee React and Angular guides
--filterUse lots of advanced project matcher syntax like -p admin-* or -p tag:api-*
--forcenx reset and then run the command again
--framework-inferenceN/A. Nx plugins infer tasks automatically as a first class feature
--global-depsUse inputs in nx.json
--graphSimilar syntax or nx graph for full interactive experience
--heapN/A. Use --verbose
--ignoreUse .nxignore or .gitignore
--log-orderUse --output-style
--no-cacheUse --skip-nx-cache
--output-logsUse --output-style
--onlyN/A
--parallelN/A
--preflightN/A
--summarizeN/A
--tokenSet Nx Cloud CI Access Token
--teamSee --token for Nx Cloud workspace selection
--traceN/A. Use --verbose
--verbosityUse --verbose
turbo genUse nx generate
turbo loginnx login - Create an Nx Cloud account
turbo linknx connect - Connect a workspace to an Nx Cloud account

For a complete list of Nx commands and options, see the Nx CLI documentation.