> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/nrwl/nx/llms.txt
> Use this file to discover all available pages before exploring further.

# How caching works

> Learn how Nx computation hashing enables powerful caching, including what factors determine cache validity and how local and remote caches work together.

Before running any cacheable task, Nx computes a **computation hash**. As long as the computation hash is the same as a previous run, Nx can replay the cached result — including terminal output and file artifacts — without executing the task again.

## What Nx hashes

By default, the computation hash for a task like `nx test remixapp` includes:

<CardGroup cols={2}>
  <Card title="Source files" icon="file-code">
    All source files of the project and its transitive dependencies in the project graph.
  </Card>

  <Card title="Global configuration" icon="settings">
    Relevant workspace-level config such as `nx.json`, `tsconfig.base.json`, and `.eslintrc.json`.
  </Card>

  <Card title="External dependency versions" icon="package">
    The resolved versions of npm packages used by the project, read from `node_modules`.
  </Card>

  <Card title="Runtime values" icon="terminal">
    User-defined runtime inputs such as the Node.js version or environment variables.
  </Card>

  <Card title="CLI flags" icon="sliders">
    Arguments passed to the task (e.g., `--configuration=production`).
  </Card>
</CardGroup>

<Note>
  This behavior is customizable. For example, lint checks may only depend on the source code of the project and global configs. Builds can depend on the compiled declaration files (`.d.ts`) of dependency libraries rather than their full source.
</Note>

## Cache lookup flow

<Steps>
  <Step title="Compute the hash">
    Nx hashes all configured inputs for the task to produce a single computation hash string.
  </Step>

  <Step title="Check the local cache">
    Nx looks for a matching hash in the local cache directory (`.nx/cache` by default).
  </Step>

  <Step title="Check the remote cache">
    If the local cache misses and a remote cache is configured (e.g., Nx Cloud), Nx checks there next.
  </Step>

  <Step title="Replay or run">
    On a cache hit, Nx restores output files to their correct locations and replays terminal output. On a miss, Nx runs the task and stores the results in the local (and optionally remote) cache.
  </Step>
</Steps>

From the user's point of view, the command ran the same — only much faster on a cache hit.

## What gets cached

Nx caches at the process level, regardless of the underlying tool:

* **Terminal output** — stdout and stderr, replayed identically including on Windows.
* **Task artifacts** — files written to the paths defined in the `outputs` property of the target configuration.
* **Computation hash** — stored alongside the result for cache invalidation checks.

### Defining outputs

Nx needs to know which files to cache. Configure `outputs` per-project or globally in `nx.json`:

<Tabs>
  <Tab title="project.json">
    ```json title="apps/myapp/project.json" theme={null}
    {
      "name": "myapp",
      "targets": {
        "build": {
          "outputs": ["dist/dist/myapp"]
        }
      }
    }
    ```
  </Tab>

  <Tab title="package.json">
    ```json title="apps/myapp/package.json" theme={null}
    {
      "name": "myapp",
      "nx": {
        "targets": {
          "build": {
            "outputs": ["{projectRoot}/build", "{projectRoot}/public/build"]
          }
        }
      }
    }
    ```
  </Tab>

  <Tab title="nx.json (global default)">
    ```json title="nx.json" theme={null}
    {
      "targetDefaults": {
        "build": {
          "dependsOn": ["^build"],
          "outputs": [
            "{projectRoot}/dist",
            "{projectRoot}/build",
            "{projectRoot}/public/build"
          ]
        }
      }
    }
    ```
  </Tab>
</Tabs>

If `outputs` is not defined for a target in either the project or `nx.json`, Nx defaults to caching `dist` and `build` at the repository root.

<Warning>
  Several executors have an `outputPath` option. That option alone does not influence caching. To use it as a cache output, reference it in the `outputs` array: `"{options.outputPath}"`.
</Warning>

## Defining cache inputs

By default, the cache considers all project files (`{projectRoot}/**/*`). You can narrow this to improve cache hit rates:

<Tabs>
  <Tab title="Globally in nx.json">
    ```json title="nx.json" theme={null}
    {
      "targetDefaults": {
        "build": {
          "inputs": ["{projectRoot}/**/*", "!{projectRoot}/**/*.md"]
        },
        "test": {
          "inputs": ["{projectRoot}/**/*", "!{projectRoot}/**/*.md"]
        }
      }
    }
    ```
  </Tab>

  <Tab title="Per-project">
    ```json title="packages/some-project/project.json" theme={null}
    {
      "name": "some-project",
      "targets": {
        "build": {
          "inputs": ["!{projectRoot}/**/*.md"]
        }
      }
    }
    ```
  </Tab>
</Tabs>

Inputs can be:

* **Source file globs** — `"{projectRoot}/**/*"`, `"{workspaceRoot}/tsconfig.base.json"`
* **Environment variables** — `{ "env": "NODE_ENV" }`
* **Runtime values** — `{ "runtime": "node --version" }`
* **External dependency versions** — `{ "externalDependencies": ["vite"] }`
* **Named input sets** — reusable groups defined in `nx.json` under `namedInputs`

## Args hash inputs

CLI flags that are passed directly to the underlying tool are included in the hash. This means `nx build remixapp` and `nx build remixapp --flag=true` produce different hashes and have separate cache entries.

However, Nx-level orchestration flags do not affect the hash. The following two commands produce identical computation hashes:

```bash theme={null}
npx nx build remixapp
npx nx run-many -t build -p remixapp
```

Similarly, when building multiple projects, each project has its own independent hash:

```bash theme={null}
# These two commands are equivalent from a caching perspective:
npx nx run-many -t build -p header footer
npx nx build header && npx nx build footer
```

## Cache invalidation

The cache is invalidated automatically whenever any input changes:

* A source file in the project or any of its dependencies is modified
* A dependency version changes in `package.json` / `node_modules`
* A referenced environment variable changes value
* A global config file included in `inputs` changes
* The CLI flags passed to the task change

There is no TTL or manual expiry — cache entries remain valid as long as their inputs are unchanged.

## Local and remote cache

<CardGroup cols={2}>
  <Card title="Local cache" icon="hard-drive">
    Stored in `.nx/cache` at the workspace root by default. Shared across runs on the same machine. Configurable via `cacheDirectory` in `nx.json`.
  </Card>

  <Card title="Remote cache" icon="cloud">
    Nx Cloud provides a shared remote cache. Cache misses on one machine can be hits on another (e.g., after CI populates the cache). Configured via `nxCloudAccessToken` or the `nx-cloud` package.
  </Card>
</CardGroup>

Nx checks the local cache first. Only on a local miss does it contact the remote cache. This minimizes network overhead when the result is already available locally.

## Optimizations

Nx applies several optimizations to make caching practical at scale:

* Captures both stdout and stderr so replayed output looks identical, including on Windows
* Tracks exactly which files go where to minimize I/O during cache restoration
* Shows only relevant output when processing a large task graph with many cache hits
* Provides tooling to diagnose cache misses (see `nx show project <name>` and the `--verbose` flag)
