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.
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.
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.
- 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)
- 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]
- 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)
- 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)
- 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)
- 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.
packages/nx/src/project-graph/project-graph.tsobject 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
packages/nx/src/config/task-graph.tsobject 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
packages/nx/src/config/nx-json.tsobject 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
packages/nx/src/config/misc-interfaces.tsobject 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
packages/nx/src/generators/generator-context.tsobject 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
packages/nx/src/config/nx-json.tsobject 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
Hidden Assumptions
Things this code relies on but never validates. These are the things that cause silent failures when the system changes.
Assumes sufficient disk space to store all task outputs in cache without checking available disk space — uses NX_CACHE_DIRECTORY or default .nx/cache directory
If this fails: 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
packages/nx/src/tasks-runner/default-tasks-runner.ts
Assumes file modification timestamps accurately reflect when source code changed, ignoring scenarios where files are touched without content changes or where filesystem timestamps are unreliable (network drives, Docker volumes)
If this fails: 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
packages/nx/src/project-graph/project-graph-builder.ts
Assumes all files in the workspace can be read simultaneously without file locking conflicts or permission issues — directly reads file contents for hashing
If this fails: 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
packages/nx/src/hasher/file-hasher.ts
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
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
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
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
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
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
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
System Behavior
How the system operates at runtime — where data accumulates, what loops, what waits, and what controls what.
Data Pools
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
Cached dependency graph stored in .nx/cache to avoid re-analyzing the entire workspace on every command — invalidated when workspace files change
Runtime registry of loaded plugins and their capabilities — maps plugin names to createNodes functions, generators, and executors
Tracks file modification timestamps and content hashes to detect changes since last run — enables incremental graph updates
Feedback Loops
- Incremental Graph Updates (cache-invalidation, balancing) — Trigger: File system changes detected. Action: Re-analyze only changed files and update affected portions of the project graph rather than rebuilding from scratch. Exit: Graph is consistent with current file system state.
- Task Retry with Backoff (retry, balancing) — Trigger: Task execution failure. Action: Re-execute failed tasks up to configured retry limit with exponential backoff between attempts. Exit: Task succeeds or max retries reached.
- Plugin Hot Reload (auto-scale, reinforcing) — Trigger: Plugin configuration changes in nx.json. Action: Reload plugin registry, re-run createNodes functions, and update project configurations without restarting the process. Exit: All plugins are loaded and project graph is updated.
Delays
- Initial Graph Build (compilation, ~2-30 seconds depending on workspace size) — First command in a workspace session must analyze all files to build the dependency graph — subsequent commands use cached graph
- Remote Cache Upload (async-processing, ~varies by network and artifact size) — Cache uploads happen in background after task completion — doesn't block subsequent tasks but may delay CI pipeline completion
- Plugin Loading (compilation, ~1-5 seconds per plugin) — Plugins are loaded and validated on first workspace access — subsequent operations reuse loaded plugins
Control Points
- NX_CACHE_DIRECTORY (env-var) — Controls: Where Nx stores cached task outputs — can be local directory or remote cache URL
- NX_PARALLEL (env-var) — Controls: Maximum number of tasks to run in parallel — defaults to number of CPU cores
- tasksRunnerOptions.parallel (threshold) — Controls: Task parallelism configuration — can be boolean or number to limit concurrent tasks
- targetDefaults (runtime-toggle) — Controls: Default configuration applied to all targets of specific types — affects caching, dependencies, and execution options
Technology Stack
Primary language for all packages — provides type safety and developer experience across the entire Nx ecosystem
Performance-critical operations like file hashing, path resolution, and native binaries — compiled to WebAssembly and native modules
UI framework for the project graph visualization app and various components in the documentation website
Powers the nx.dev documentation website with static generation, API routes, and dynamic content rendering
Unit testing framework for all packages — also provides the Jest plugin for user workspaces
Package manager for the monorepo — handles workspace dependencies and provides efficient disk usage through content-addressed storage
Local npm registry for E2E testing — allows testing plugin installation and publishing workflows in isolation
Key Components
- TaskRunner (orchestrator) — Coordinates task execution across multiple processes, manages the task queue, handles caching and cache retrieval, and reports execution status — the core scheduler that makes Nx fast
packages/nx/src/tasks-runner/default-tasks-runner.ts - ProjectGraphBuilder (processor) — Analyzes workspace files to build the dependency graph — scans TypeScript imports, package.json dependencies, and plugin-detected relationships to understand what depends on what
packages/nx/src/project-graph/project-graph-builder.ts - FileHasher (processor) — Computes content-based hashes for files and directories, enabling cache invalidation when source code changes — the foundation of Nx's incremental builds
packages/nx/src/hasher/file-hasher.ts - TaskHasher (processor) — Computes unique hashes for tasks by combining input file hashes, configuration options, and dependency hashes — determines if a task can be restored from cache
packages/nx/src/hasher/task-hasher.ts - Cache (store) — Stores and retrieves task outputs (built files, test results, etc.) using task hashes as keys — local filesystem cache plus optional remote cache integration
packages/nx/src/tasks-runner/cache.ts - PluginManager (registry) — Loads, validates, and manages Nx plugins — discovers createNodes functions, processes project configurations, and coordinates plugin lifecycle
packages/nx/src/project-graph/plugins/plugin-manager.ts - WorkspaceContext (store) — Maintains workspace state including project configurations, file mappings, and plugin registrations — the central data store for workspace information
packages/nx/src/utils/workspace-context.ts - AffectedProjectGraphBuilder (processor) — Analyzes git changes to determine which projects are affected by modifications — walks dependency graph to find all projects impacted by changed files
packages/nx/src/project-graph/affected/affected-project-graph-builder.ts - RunCommandHandler (dispatcher) — Processes 'nx run' commands by parsing target specifications, building task graphs, and delegating to the task runner — main entry point for task execution
packages/nx/src/command-line/run/run.ts - Generator (executor) — Executes code generation and modification tasks — creates new files, updates existing ones, and modifies project configurations based on generator schemas
packages/nx/src/generators/generator.ts
Package Structure
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.
Shared utilities and types for building Nx plugins — provides APIs for file manipulation, AST processing, project configuration, and workspace interaction.
Angular framework plugin providing generators for Angular apps and libraries, executors for building and testing, and integration with Angular CLI tools.
React framework plugin with generators for React apps and components, Webpack/Vite build integration, and testing setup.
Next.js framework plugin providing generators for Next.js applications, build executors, and deployment configurations.
Jest testing integration plugin that configures Jest for Nx workspaces, provides test executors, and manages test configuration.
Webpack build system integration providing webpack executors, configuration generators, and build optimization for Nx projects.
Vite build tool integration offering fast development servers, optimized builds, and Vite configuration management.
Cypress E2E testing integration providing Cypress configuration, test runners, and component testing setup.
ESLint integration plugin that configures linting for Nx workspaces, provides lint executors, and manages ESLint configurations.
CLI tool for creating new Nx workspaces — handles preset selection, dependency installation, and initial project setup.
Interactive React application for visualizing project dependency graphs, task relationships, and workspace structure.
The nx.dev documentation website built with Next.js — includes docs, guides, API references, and interactive examples.
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 CodeSeaRelated 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 Karolina Sarna.