Turborepo Caching

Optimize monorepo builds with Turborepo caching strategies

✨ The solution you've been looking for

Verified
Tested and verified by our team
25450 Stars

Configure Turborepo for efficient monorepo builds with local and remote caching. Use when setting up Turborepo, optimizing build pipelines, or implementing distributed caching.

turborepo monorepo caching build-optimization ci-cd automation performance javascript
Repository

See It In Action

Interactive preview & real-world examples

Live Demo
Skill Demo Animation

AI Conversation Simulator

See how users interact with this skill

User Prompt

Help me set up Turborepo for a new monorepo with React apps and shared packages

Skill Processing

Analyzing request...

Agent Response

Complete turbo.json configuration with pipeline definitions, caching rules, and workspace structure

Quick Start (3 Steps)

Get up and running in minutes

1

Install

claude-code skill install turborepo-caching

claude-code skill install turborepo-caching
2

Config

3

First Trigger

@turborepo-caching help

Commands

CommandDescriptionRequired Args
@turborepo-caching new-turborepo-setupConfigure a fresh monorepo with optimal caching from the startNone
@turborepo-caching ci/cd-optimizationImplement remote caching to speed up continuous integration buildsNone
@turborepo-caching cache-performance-debuggingIdentify and resolve cache misses and build performance issuesNone

Typical Use Cases

New Turborepo Setup

Configure a fresh monorepo with optimal caching from the start

CI/CD Optimization

Implement remote caching to speed up continuous integration builds

Cache Performance Debugging

Identify and resolve cache misses and build performance issues

Overview

Turborepo Caching

Production patterns for Turborepo build optimization.

When to Use This Skill

  • Setting up new Turborepo projects
  • Configuring build pipelines
  • Implementing remote caching
  • Optimizing CI/CD performance
  • Migrating from other monorepo tools
  • Debugging cache misses

Core Concepts

1. Turborepo Architecture

Workspace Root/
├── apps/
│   ├── web/
│   │   └── package.json
│   └── docs/
│       └── package.json
├── packages/
│   ├── ui/
│   │   └── package.json
│   └── config/
│       └── package.json
├── turbo.json
└── package.json

2. Pipeline Concepts

ConceptDescription
dependsOnTasks that must complete first
cacheWhether to cache outputs
outputsFiles to cache
inputsFiles that affect cache key
persistentLong-running tasks (dev servers)

Templates

Template 1: turbo.json Configuration

 1{
 2  "$schema": "https://turbo.build/schema.json",
 3  "globalDependencies": [".env", ".env.local"],
 4  "globalEnv": ["NODE_ENV", "VERCEL_URL"],
 5  "pipeline": {
 6    "build": {
 7      "dependsOn": ["^build"],
 8      "outputs": ["dist/**", ".next/**", "!.next/cache/**"],
 9      "env": ["API_URL", "NEXT_PUBLIC_*"]
10    },
11    "test": {
12      "dependsOn": ["build"],
13      "outputs": ["coverage/**"],
14      "inputs": ["src/**/*.tsx", "src/**/*.ts", "test/**/*.ts"]
15    },
16    "lint": {
17      "outputs": [],
18      "cache": true
19    },
20    "typecheck": {
21      "dependsOn": ["^build"],
22      "outputs": []
23    },
24    "dev": {
25      "cache": false,
26      "persistent": true
27    },
28    "clean": {
29      "cache": false
30    }
31  }
32}

Template 2: Package-Specific Pipeline

 1// apps/web/turbo.json
 2{
 3  "$schema": "https://turbo.build/schema.json",
 4  "extends": ["//"],
 5  "pipeline": {
 6    "build": {
 7      "outputs": [".next/**", "!.next/cache/**"],
 8      "env": ["NEXT_PUBLIC_API_URL", "NEXT_PUBLIC_ANALYTICS_ID"]
 9    },
10    "test": {
11      "outputs": ["coverage/**"],
12      "inputs": ["src/**", "tests/**", "jest.config.js"]
13    }
14  }
15}

Template 3: Remote Caching with Vercel

 1# Login to Vercel
 2npx turbo login
 3
 4# Link to Vercel project
 5npx turbo link
 6
 7# Run with remote cache
 8turbo build --remote-only
 9
10# CI environment variables
11TURBO_TOKEN=your-token
12TURBO_TEAM=your-team
 1# .github/workflows/ci.yml
 2name: CI
 3
 4on:
 5  push:
 6    branches: [main]
 7  pull_request:
 8
 9env:
10  TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
11  TURBO_TEAM: ${{ vars.TURBO_TEAM }}
12
13jobs:
14  build:
15    runs-on: ubuntu-latest
16    steps:
17      - uses: actions/checkout@v4
18
19      - uses: actions/setup-node@v4
20        with:
21          node-version: 20
22          cache: "npm"
23
24      - name: Install dependencies
25        run: npm ci
26
27      - name: Build
28        run: npx turbo build --filter='...[origin/main]'
29
30      - name: Test
31        run: npx turbo test --filter='...[origin/main]'

Template 4: Self-Hosted Remote Cache

 1// Custom remote cache server (Express)
 2import express from "express";
 3import { createReadStream, createWriteStream } from "fs";
 4import { mkdir } from "fs/promises";
 5import { join } from "path";
 6
 7const app = express();
 8const CACHE_DIR = "./cache";
 9
10// Get artifact
11app.get("/v8/artifacts/:hash", async (req, res) => {
12  const { hash } = req.params;
13  const team = req.query.teamId || "default";
14  const filePath = join(CACHE_DIR, team, hash);
15
16  try {
17    const stream = createReadStream(filePath);
18    stream.pipe(res);
19  } catch {
20    res.status(404).send("Not found");
21  }
22});
23
24// Put artifact
25app.put("/v8/artifacts/:hash", async (req, res) => {
26  const { hash } = req.params;
27  const team = req.query.teamId || "default";
28  const dir = join(CACHE_DIR, team);
29  const filePath = join(dir, hash);
30
31  await mkdir(dir, { recursive: true });
32
33  const stream = createWriteStream(filePath);
34  req.pipe(stream);
35
36  stream.on("finish", () => {
37    res.json({
38      urls: [`${req.protocol}://${req.get("host")}/v8/artifacts/${hash}`],
39    });
40  });
41});
42
43// Check artifact exists
44app.head("/v8/artifacts/:hash", async (req, res) => {
45  const { hash } = req.params;
46  const team = req.query.teamId || "default";
47  const filePath = join(CACHE_DIR, team, hash);
48
49  try {
50    await fs.access(filePath);
51    res.status(200).end();
52  } catch {
53    res.status(404).end();
54  }
55});
56
57app.listen(3000);
1// turbo.json for self-hosted cache
2{
3  "remoteCache": {
4    "signature": false
5  }
6}
1# Use self-hosted cache
2turbo build --api="http://localhost:3000" --token="my-token" --team="my-team"

Template 5: Filtering and Scoping

 1# Build specific package
 2turbo build --filter=@myorg/web
 3
 4# Build package and its dependencies
 5turbo build --filter=@myorg/web...
 6
 7# Build package and its dependents
 8turbo build --filter=...@myorg/ui
 9
10# Build changed packages since main
11turbo build --filter='...[origin/main]'
12
13# Build packages in directory
14turbo build --filter='./apps/*'
15
16# Combine filters
17turbo build --filter=@myorg/web --filter=@myorg/docs
18
19# Exclude package
20turbo build --filter='!@myorg/docs'
21
22# Include dependencies of changed
23turbo build --filter='...[HEAD^1]...'

Template 6: Advanced Pipeline Configuration

 1{
 2  "$schema": "https://turbo.build/schema.json",
 3  "pipeline": {
 4    "build": {
 5      "dependsOn": ["^build"],
 6      "outputs": ["dist/**"],
 7      "inputs": ["$TURBO_DEFAULT$", "!**/*.md", "!**/*.test.*"]
 8    },
 9    "test": {
10      "dependsOn": ["^build"],
11      "outputs": ["coverage/**"],
12      "inputs": ["src/**", "tests/**", "*.config.*"],
13      "env": ["CI", "NODE_ENV"]
14    },
15    "test:e2e": {
16      "dependsOn": ["build"],
17      "outputs": [],
18      "cache": false
19    },
20    "deploy": {
21      "dependsOn": ["build", "test", "lint"],
22      "outputs": [],
23      "cache": false
24    },
25    "db:generate": {
26      "cache": false
27    },
28    "db:push": {
29      "cache": false,
30      "dependsOn": ["db:generate"]
31    },
32    "@myorg/web#build": {
33      "dependsOn": ["^build", "@myorg/db#db:generate"],
34      "outputs": [".next/**"],
35      "env": ["NEXT_PUBLIC_*"]
36    }
37  }
38}

Template 7: Root package.json Setup

 1{
 2  "name": "my-turborepo",
 3  "private": true,
 4  "workspaces": ["apps/*", "packages/*"],
 5  "scripts": {
 6    "build": "turbo build",
 7    "dev": "turbo dev",
 8    "lint": "turbo lint",
 9    "test": "turbo test",
10    "clean": "turbo clean && rm -rf node_modules",
11    "format": "prettier --write \"**/*.{ts,tsx,md}\"",
12    "changeset": "changeset",
13    "version-packages": "changeset version",
14    "release": "turbo build --filter=./packages/* && changeset publish"
15  },
16  "devDependencies": {
17    "turbo": "^1.10.0",
18    "prettier": "^3.0.0",
19    "@changesets/cli": "^2.26.0"
20  },
21  "packageManager": "npm@10.0.0"
22}

Debugging Cache

 1# Dry run to see what would run
 2turbo build --dry-run
 3
 4# Verbose output with hashes
 5turbo build --verbosity=2
 6
 7# Show task graph
 8turbo build --graph
 9
10# Force no cache
11turbo build --force
12
13# Show cache status
14turbo build --summarize
15
16# Debug specific task
17TURBO_LOG_VERBOSITY=debug turbo build --filter=@myorg/web

Best Practices

Do’s

  • Define explicit inputs - Avoid cache invalidation
  • Use workspace protocol - "@myorg/ui": "workspace:*"
  • Enable remote caching - Share across CI and local
  • Filter in CI - Build only affected packages
  • Cache build outputs - Not source files

Don’ts

  • Don’t cache dev servers - Use persistent: true
  • Don’t include secrets in env - Use runtime env vars
  • Don’t ignore dependsOn - Causes race conditions
  • Don’t over-filter - May miss dependencies

Resources

What Users Are Saying

Real feedback from the community

Environment Matrix

Dependencies

Node.js 16+
npm/yarn/pnpm
Turborepo 1.10.0+

Framework Support

Next.js ✓ (recommended) React ✓ Express ✓ TypeScript ✓

Context Window

Token Usage ~3K-8K tokens for complex monorepo configurations

Security & Privacy

Information

Author
wshobson
Updated
2026-01-30
Category
automation-tools