Skip to main content
In a monorepo, tasks rarely run in isolation. Building myapp requires building shared-ui and feat-products first. Nx manages these relationships through a task pipeline — a set of rules that determine execution order and parallelism.

Why pipelines matter

Without a task pipeline, you have two bad options:
  1. Run tasks serially in a manually maintained order — slow and brittle as the repo grows.
  2. Run all tasks in parallel — broken, because some tasks depend on the outputs of others.
Nx’s task pipeline gives you the best of both: tasks that can run concurrently do run concurrently, while tasks that have dependencies wait for those dependencies to complete.
In this example, shared-ui:build and feat-products:build are sequenced correctly, and anything that doesn’t share a dependency edge runs in parallel.

Configuring task dependencies

Task dependencies are declared with the dependsOn property. You can set this globally in nx.json under targetDefaults, or locally in a project’s project.json or package.json.

Global defaults in nx.json

nx.json
With this configuration, running nx test myproj causes Nx to:
  1. Run myproj:build first (because test depends on build of the same project)
  2. Run build for all of myproj’s dependencies first (because build depends on ^build — the ^ means “dependencies in the project graph”)
  3. Run myproj:prebuild before myproj:build (same-project dependency without ^)

Per-project configuration

Project-level configuration overrides global defaults for that project only:
apps/myapp/project.json

The dependsOn syntax

The ^ prefix means “run this target for all projects that this project depends on in the project graph.” This is the most common pattern for build tasks, ensuring that library builds complete before app builds start.
Without a ^, the dependency refers to a target on the same project. This lets you chain targets within a single project.
You can also declare dependencies on specific named projects:

Parallelism

Nx runs as many tasks in parallel as the dependency constraints allow. The default parallelism limit is 3 concurrent tasks. You can override this with --parallel:
Tasks that share a dependency edge always run sequentially in the correct order. Only tasks with no dependency relationship between them run in parallel.

Example: parallel vs. sequential

Given three projects where app1 and app2 both depend on lib:
nx.json
Running nx run-many -t build produces this execution order:
Both app builds start as soon as lib:build completes. Nx does not wait for one app to finish before starting the other.

Mixing targets in one run

Task graphs can contain different targets running simultaneously. For instance, while Nx is building app2, it can be testing app1 at the same time — as long as neither task depends on the other.

Scope of configuration

Project-level configuration always wins over targetDefaults.
See the Configuration reference for all targetDefaults options including advanced patterns like cross-target dependencies and self-referential dependsOn.