nrwl/nx

The Monorepo Platform that amplifies both developers and AI agents. Nx optimizes your builds, scales your CI, and fixes failed PRs automatically. Ship in half the time.

28,561 stars TypeScript 10 components

15 hidden assumptions · 6-stage pipeline · 10 components

Like any codebase, this fullstack makes assumptions it never checks — most are routine. The ones worth your attention are below.

Caches build outputs and runs affected tasks in polyglot monorepos

When users run 'nx build myapp', Nx first loads the workspace configuration and plugin definitions from nx.json and project.json files. It then analyzes all source files to build a project dependency graph, calculates which projects are affected by recent changes, creates a task graph for the requested operation, computes cache hashes for each task, checks if cached results exist, executes only the tasks that need to run (either because they're not cached or their inputs changed), and finally stores the outputs in the cache for future use. Throughout this process, the task runner coordinates parallel execution across available CPU cores.

Under the hood, the system uses 3 feedback loops, 4 data pools, 4 control points to manage its runtime behavior.

A 10-component fullstack. 4811 files analyzed. Data flows through 6 distinct pipeline stages.

Hidden Assumptions

Most of what this code assumes is routine. These 3 are the ones most likely to cause trouble here. The rest are minor; they're under "Show everything".

Worth your attention first

When disk space runs low during cache writes, tasks may fail silently or corrupt cached artifacts, causing subsequent builds to restore invalid results or fail unexpectedly

Worth your attention first

Nx may rebuild unnecessarily when files are touched but not changed, or miss rebuilds when content changes but timestamps don't update, leading to stale builds in production

Worth your attention first

On Windows or when files are locked by IDEs/processes, hash computation fails causing cache misses and forcing unnecessary rebuilds, or crashes with EACCES/EBUSY errors

Show everything (12 more)
Scale

Assumes NX_PARALLEL environment variable or tasksRunnerOptions.parallel number will not exceed system memory capacity when spawning concurrent task processes

If this fails: Setting parallel tasks too high can cause OOM kills of task processes, leading to cryptic failures and incomplete builds without clear error messages about resource exhaustion

packages/nx/src/tasks-runner/default-tasks-runner.ts
Contract

Assumes plugin createNodes functions return consistent project configurations between invocations with same inputs — doesn't validate that plugins are deterministic

If this fails: Non-deterministic plugins cause project graph to change randomly between runs, invalidating caches unpredictably and causing inconsistent build behavior across team members

packages/nx/src/project-graph/plugins/plugin-manager.ts
Ordering

Assumes task outputs can be safely restored from cache without considering order of restoration — restores all cached files simultaneously

If this fails: If cached files have interdependencies or specific restoration order requirements, parallel restoration may create partially-valid build states or overwrite files incorrectly

packages/nx/src/tasks-runner/cache.ts
Domain

Assumes file paths are normalized consistently across different operating systems when computing task hashes — may use platform-specific path separators in hash inputs

If this fails: Same source code produces different task hashes on Windows vs Unix, preventing cache sharing in mixed CI environments and forcing redundant rebuilds

packages/nx/src/hasher/task-hasher.ts
Resource

Assumes all TypeScript/JavaScript files in the workspace can be parsed by the TypeScript compiler without memory limits — loads entire files into memory for dependency analysis

If this fails: Very large source files or workspaces with thousands of files may cause Node.js to run out of heap memory during graph analysis, crashing with out-of-memory errors

packages/nx/src/project-graph/project-graph-builder.ts
Temporal

Assumes git base commit exists and is accessible when calculating affected projects — uses affected.defaultBase configuration or git merge-base

If this fails: In shallow clones or when base commit is not available, affected calculation fails causing all projects to be marked as affected, destroying incremental build benefits

packages/nx/src/project-graph/affected/affected-project-graph-builder.ts
Environment

Assumes tsquery can successfully parse and modify any JavaScript/TypeScript file structure in cypress.config files — directly manipulates AST without validation

If this fails: Malformed or unusual cypress config syntax causes AST parsing to fail, corrupting config files or failing silently without applying necessary e2e configuration changes

packages/cypress/src/utils/config.ts:addDefaultE2EConfig
Contract

Assumes Task objects will always have valid project and target strings that correspond to real projects and targets in the workspace — no validation against current project graph

If this fails: Stale or invalid tasks referencing deleted projects/targets get executed, causing runtime errors or executing against wrong project configurations

packages/nx/src/config/task-graph.ts
Scale

Assumes NX_CACHE_DIRECTORY path length will not exceed filesystem limits and that nested cache directory structures won't hit path length constraints on Windows (260 character limit)

If this fails: Deep project hierarchies or long project names cause cache writes to fail with ENAMETOOLONG errors, disabling caching entirely for affected projects

packages/nx/src/utils/cache-directory.ts
Environment

Assumes commandsObject.argv will successfully parse command line arguments and that Node.js environment supports the expected argument format

If this fails: Unusual shell environments or argument parsing edge cases may cause workspace creation to fail silently or with confusing error messages

packages/create-nx-workspace/bin/index.ts
Domain

Assumes plugin names in plugins array correspond to actual installable npm packages or local plugin files — no validation that plugins exist before attempting to load

If this fails: Typos in plugin names or missing plugin dependencies cause workspace initialization to fail with unclear module resolution errors

packages/nx/src/config/nx-json.ts
Temporal

Assumes file system watcher state remains consistent between file change events — doesn't handle rapid successive changes to the same file

If this fails: Fast file modifications may cause incomplete change detection, missing some affected projects in incremental builds or causing race conditions in graph updates

packages/nx/src/file-utils.ts

Open the standalone hidden-assumptions report for nx →

How Data Flows Through the System

When users run 'nx build myapp', Nx first loads the workspace configuration and plugin definitions from nx.json and project.json files. It then analyzes all source files to build a project dependency graph, calculates which projects are affected by recent changes, creates a task graph for the requested operation, computes cache hashes for each task, checks if cached results exist, executes only the tasks that need to run (either because they're not cached or their inputs changed), and finally stores the outputs in the cache for future use. Throughout this process, the task runner coordinates parallel execution across available CPU cores.

  1. Load workspace configuration — WorkspaceContext reads nx.json, project.json files, and package.json to understand workspace structure, plugin configurations, and project settings (config: plugins, targetDefaults, namedInputs)
  2. Build project graph — ProjectGraphBuilder scans all workspace files, analyzes TypeScript imports and package.json dependencies, invokes plugin createNodes functions, and constructs the complete dependency graph showing how projects relate to each other [NxJsonConfiguration → ProjectGraph]
  3. Calculate affected projects — AffectedProjectGraphBuilder compares current file hashes against git base commit, identifies changed files, walks the dependency graph to find all projects that directly or transitively depend on changed code [ProjectGraph → AffectedProjects] (config: affected.defaultBase)
  4. Create task graph — RunCommandHandler parses the target specification (e.g. 'build'), resolves project configurations and target defaults, builds dependency chains between tasks based on dependsOn declarations, and creates the execution plan [ProjectGraph → Task] (config: targetDefaults)
  5. Compute task hashes — TaskHasher combines file content hashes from inputs, task configuration options, runtime values, and dependency task hashes to create a unique cache key that represents the task's complete state [Task → TaskHash] (config: namedInputs)
  6. Check cache and execute tasks — TaskRunner checks the Cache for existing results using task hashes, restores cached outputs when available, executes remaining tasks in parallel across multiple processes, and stores new outputs to cache [TaskHash → CacheResult] (config: cacheDirectory, tasksRunnerOptions)

Data Models

The data structures that flow between stages — the contracts that hold the system together.

ProjectGraph packages/nx/src/project-graph/project-graph.ts
object with nodes: Record<string, ProjectGraphProjectNode>, dependencies: Record<string, ProjectGraphDependency[]>, allWorkspaceFiles: FileData[], fileMap: ProjectFileMap
Built by analyzing source files and project configurations, cached to nx-cache, and used to determine what needs to be rebuilt when files change
Task packages/nx/src/config/task-graph.ts
object with id: string, target: { project: string, target: string, configuration?: string }, overrides: object, outputs: string[], startTime?: number, endTime?: number
Created from target configurations during task scheduling, executed by task runners, and cached with their outputs for future runs
NxJsonConfiguration packages/nx/src/config/nx-json.ts
object with npmScope?: string, affected?: AffectedConfig, implicitDependencies?: Record<string, '*'|string[]>, targetDefaults?: Record<string, TargetDefaults>, plugins?: (string|PluginConfiguration)[]
Loaded at workspace initialization from nx.json, merged with plugin configurations, and used to configure global Nx behavior throughout execution
ExecutorContext packages/nx/src/config/misc-interfaces.ts
object with root: string, cwd: string, projectName?: string, targetName?: string, configurationName?: string, projectGraph: ProjectGraph, taskGraph: TaskGraph
Created by the task runner for each task execution, passed to plugin executors to provide workspace context and project information
GeneratorContext packages/nx/src/generators/generator-context.ts
object with root: string, projectName?: string, projectsConfigurations?: ProjectsConfigurations, projectGraph?: ProjectGraph, logger: Logger
Created when generators are invoked, provides workspace state and utilities for generating or modifying code and configuration files
PluginConfiguration packages/nx/src/config/nx-json.ts
object with plugin: string, options?: object, include?: string[], exclude?: string[]
Defined in nx.json plugins array, processed during workspace initialization to register plugin capabilities and configure automatic project detection

System Behavior

How the system operates at runtime — where data accumulates, what loops, what waits, and what controls what.

Data Pools

Nx Cache (file-store)
Stores task outputs indexed by task hashes — includes built artifacts, test results, and any files produced by tasks, with optional remote cache integration for team sharing
Project Graph Cache (file-store)
Cached dependency graph stored in .nx/cache to avoid re-analyzing the entire workspace on every command — invalidated when workspace files change
Plugin Registry (in-memory)
Runtime registry of loaded plugins and their capabilities — maps plugin names to createNodes functions, generators, and executors
File System Watcher State (in-memory)
Tracks file modification timestamps and content hashes to detect changes since last run — enables incremental graph updates

Feedback Loops

Delays

Control Points

Technology Stack

TypeScript (runtime)
Primary language for all packages — provides type safety and developer experience across the entire Nx ecosystem
Rust (runtime)
Performance-critical operations like file hashing, path resolution, and native binaries — compiled to WebAssembly and native modules
React (framework)
UI framework for the project graph visualization app and various components in the documentation website
Next.js (framework)
Powers the nx.dev documentation website with static generation, API routes, and dynamic content rendering
Jest (testing)
Unit testing framework for all packages — also provides the Jest plugin for user workspaces
pnpm (build)
Package manager for the monorepo — handles workspace dependencies and provides efficient disk usage through content-addressed storage
Verdaccio (testing)
Local npm registry for E2E testing — allows testing plugin installation and publishing workflows in isolation

Key Components

Package Structure

nx (app)
The core Nx engine that orchestrates task execution, manages caching, builds dependency graphs, and coordinates the plugin ecosystem. Contains the main CLI, task runner, and all core functionality.
devkit (library)
Shared utilities and types for building Nx plugins — provides APIs for file manipulation, AST processing, project configuration, and workspace interaction.
angular (library)
Angular framework plugin providing generators for Angular apps and libraries, executors for building and testing, and integration with Angular CLI tools.
react (library)
React framework plugin with generators for React apps and components, Webpack/Vite build integration, and testing setup.
next (library)
Next.js framework plugin providing generators for Next.js applications, build executors, and deployment configurations.
jest (library)
Jest testing integration plugin that configures Jest for Nx workspaces, provides test executors, and manages test configuration.
webpack (library)
Webpack build system integration providing webpack executors, configuration generators, and build optimization for Nx projects.
vite (library)
Vite build tool integration offering fast development servers, optimized builds, and Vite configuration management.
cypress (library)
Cypress E2E testing integration providing Cypress configuration, test runners, and component testing setup.
eslint (library)
ESLint integration plugin that configures linting for Nx workspaces, provides lint executors, and manages ESLint configurations.
create-nx-workspace (app)
CLI tool for creating new Nx workspaces — handles preset selection, dependency installation, and initial project setup.
graph-client (app)
Interactive React application for visualizing project dependency graphs, task relationships, and workspace structure.
nx-dev (app)
The nx.dev documentation website built with Next.js — includes docs, guides, API references, and interactive examples.
e2e-utils (shared)
Shared utilities for E2E testing including workspace creation, test project management, and local registry setup.

Explore the interactive analysis

See the full architecture map, data flow, and code patterns visualization.

Analyze on CodeSea

Related Fullstack Repositories

Frequently Asked Questions

What is nx used for?

Caches build outputs and runs affected tasks in polyglot monorepos nrwl/nx is a 10-component fullstack written in TypeScript. Data flows through 6 distinct pipeline stages. The codebase contains 4811 files.

How is nx architected?

nx is organized into 5 architecture layers: Core Engine, Framework Plugins, Developer Tools, Documentation Platform, and 1 more. Data flows through 6 distinct pipeline stages. This layered structure keeps concerns separated and modules independent.

How does data flow through nx?

Data moves through 6 stages: Load workspace configuration → Build project graph → Calculate affected projects → Create task graph → Compute task hashes → .... When users run 'nx build myapp', Nx first loads the workspace configuration and plugin definitions from nx.json and project.json files. It then analyzes all source files to build a project dependency graph, calculates which projects are affected by recent changes, creates a task graph for the requested operation, computes cache hashes for each task, checks if cached results exist, executes only the tasks that need to run (either because they're not cached or their inputs changed), and finally stores the outputs in the cache for future use. Throughout this process, the task runner coordinates parallel execution across available CPU cores. This pipeline design reflects a complex multi-stage processing system.

What technologies does nx use?

The core stack includes TypeScript (Primary language for all packages — provides type safety and developer experience across the entire Nx ecosystem), Rust (Performance-critical operations like file hashing, path resolution, and native binaries — compiled to WebAssembly and native modules), React (UI framework for the project graph visualization app and various components in the documentation website), Next.js (Powers the nx.dev documentation website with static generation, API routes, and dynamic content rendering), Jest (Unit testing framework for all packages — also provides the Jest plugin for user workspaces), pnpm (Package manager for the monorepo — handles workspace dependencies and provides efficient disk usage through content-addressed storage), and 1 more. A focused set of dependencies that keeps the build manageable.

What system dynamics does nx have?

nx exhibits 4 data pools (Nx Cache, Project Graph Cache), 3 feedback loops, 4 control points, 3 delays. The feedback loops handle cache-invalidation and retry. These runtime behaviors shape how the system responds to load, failures, and configuration changes.

What design patterns does nx use?

5 design patterns detected: Plugin Architecture, Task Graph Scheduling, Content-Based Caching, Incremental Analysis, Distributed Task Execution.

Analyzed on April 20, 2026 by CodeSea. Written by .