Monorepo CI: Nx/Turborepo caching strategies — Crash Course — Practical Guide (Oct 22, 2025)
Level: Intermediate
Monorepo CI: Nx/Turborepo Caching Strategies — Crash Course
October 22, 2025
Monorepos have surged in popularity for managing codebases at scale, especially in organisations juggling multiple projects and teams. Nx and Turborepo stand out as modern toolchains providing first-class support for monorepos, focussed on scalable builds and incremental workflows.
A crucial factor for efficient Continuous Integration (CI) of monorepos is caching: reusing previously computed build and test results to avoid redundant work. This article provides an intermediate-level, hands-on guide to contemporary caching strategies in Nx and Turborepo, highlighting version-relevant features as of late 2025.
Prerequisites
- Familiarity with monorepo concepts and CI basics.
- Basic knowledge of Nx (version 16+) or Turborepo (version 1.6+).
- Node.js environment configured (Node 18+ recommended).
- Access to a supported CI platform (GitHub Actions, GitLab CI, CircleCI, etc.).
- Understanding of basic caching principles (local and remote cache).
Hands-on steps
1. Understanding Local vs Remote Cache
Both Nx and Turborepo leverage two types of caches:
- Local cache: Stored on the developer’s machine or the CI runner. Speeds up incremental builds within the same environment.
- Remote cache: Persisted in a shared storage service (e.g., cloud storage, Redis, or dedicated remote cache providers). Enables cache sharing across CI jobs and between developers.
Remote caching is essential for speeding up CI pipelines by reusing outputs built in previous runs on different agents.
2. Setting up Nx Remote Caching (Nx 16+)
Nx integrates remote caching natively with backends like @nx-cloud. Here’s the minimal setup for enabling Nx Cloud remote caching in CI:
# Install Nx Cloud plugin (if not already installed)
npm install --save-dev @nrwl/nx-cloud
# Enable Nx Cloud in nx.json:
{
"tasksRunnerOptions": {
"default": {
"runner": "@nrwl/nx-cloud",
"options": {
"accessToken": "your-nx-cloud-token",
"cacheableOperations": ["build", "test", "lint"],
"canTrackAnalytics": false,
"showUsageWarnings": true
}
}
}
}
In CI, add environment variables or secrets for NX_CLOUD_ACCESS_TOKEN. Nx will automatically upload/download from the remote cache to speed up any repeated tasks.
3. Configuring Turborepo Remote Cache (v1.6+)
Turborepo also supports remote caching with built-in support for Vercel’s Turbo Cloud or arbitrary remote URLs:
{
"$schema": "https://turborepo.org/schema.json",
"pipeline": {
"build": {
"outputs": ["dist/**", ".next/**"],
"cache": true
},
"test": {
"cache": true
}
},
"remoteCache": {
"enabled": true,
"url": "https://cache.example.com/api/v1/cache",
"headers": {
"Authorization": "Bearer ${TOKEN}"
}
}
}
Replace url and headers with your cache server details or use Turborepo’s default cloud cache. On CI, export your token securely for authentication.
4. Leveraging Output Hashing
Both tools use output hashing to uniquely identify task outputs based on inputs — source files, environment variables, dependencies, etc. This ensures cache correctness by preventing invalid reuse.
For Nx specifically, you can configure the hashing behaviour in nx.json under hashing options.
5. CI Cache Restoration and Persistence
Besides remote caches, configure your CI pipelines to restore and save local cache folders to speed up tasks inside the same job or between steps. For example, in GitHub Actions:
steps:
- uses: actions/checkout@v3
- name: Restore Nx cache
uses: actions/cache@v3
with:
path: |
~/.nx/cache
node_modules/.cache
key: ${{ runner.os }}-nx-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/nx.json') }}
- name: Run Nx build
run: nx build
- name: Save Nx cache
uses: actions/cache@v3
with:
path: ~/.nx/cache
key: ${{ runner.os }}-nx-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/nx.json') }}
Adapt path keys and commands as appropriate for Turborepo or other CI environments.
Common pitfalls
- Cache consistency: Cache can become invalid if environment variables or secret-dependent inputs change without updating related cache keys.
- Missing outputs config: Failure to correctly specify outputs in
turbo.jsonornx.jsoncauses cache misses or stale results. - Over-caching: Caching extremely large outputs or transient files (logs, temporary files) bloats caches and slows CI.
- Partial cache sharing: Remote cache benefits are limited if not all CI jobs share identical cache keys or tokens, resulting in cache misses.
- Immutable dependencies: Using mutable version ranges (e.g.
^or~) without lockfiles can cause cache invalidation unexpectedly.
Validation
- Run a full build in CI and confirm cache misses on the first run (logs should indicate no hits).
- Run the same CI job a second time; expected results:
- Cache hits for build/test steps appear in logs.
- Consider metrics Nx or Turborepo output on cache hit ratio.
- Test invalidating the cache: e.g. change a source file and verify cache misses for affected tasks, hits for unaffected ones.
- Verify local caching on developer machines with repeated runs.
Checklist / TL;DR
- Enable remote caching via
@nrwl/nx-cloud(Nx 16+) orremoteCachein Turborepo (v1.6+). - Ensure proper outputs configuration for all build/test targets.
- Set up CI environment vars/secrets for remote cache authentication.
- Configure CI cache restore/save steps for local cache persistence.
- Use output hashing to maintain cache integrity.
- Validate caching behaviour through multiple CI runs.
- Monitor and prune cache to avoid bloat, especially in large repos.
When to choose Nx vs Turborepo caching?
Nx integrates tightly with Angular, React, and backend frameworks, with a rich plugin ecosystem and official remote caching support via Nx Cloud. Preferred if you want a mature monorepo ecosystem with extensive task orchestration capabilities.
Turborepo, now owned by Vercel, excels at simplicity and out-of-the-box developer experience, especially for frontend-centric monorepos and incremental builds. Its caching is seamless with zero-config defaults but can be customised extensively.
Your choice depends on your stack, ecosystem alignment, and whether you need deeper orchestration (Nx) or straightforward speed and simplicity (Turborepo).