Monorepo Build Graph Optimization
Strategies to reduce monorepo build time through change impact calculation and cache key design

Introduction
Monorepo is highly collaborative, but CI quickly becomes a bottleneck if you don't manage the build graph. If full rebuilds become the default, waiting times for even small changes will increase, breaking the development rhythm. This article summarizes the dependency graph-based incremental build strategy.

Problem definition
The cost of building a monorepo depends on graph design rather than repository size.
- The scope of change impact cannot be calculated because the package boundary is ambiguous.
- Because the cache key is simple, cache misses occur frequently even with the same input.
- Because the test scope is excessive, jobs unrelated to core changes are executed.
The key is to declare the graph in code and have the pipeline trust it. The affected-only strategy should be the default.
Key concepts
| perspective | Design criteria | Verification points |
|---|---|---|
| graph declaration | Specifying package dependencies | Impact calculation accuracy |
| Incremental Build | run affected target | Average Build Time |
| remote cache | hash-based reuse | cache hit ratio |
| Test Optimization | Test by change boundary | Unnecessary miscellaneous rate |
Monorepo optimization involves defining rules before introducing tools. Strictly managing package boundaries simplifies the build graph and stabilizes performance.
Code example 1: Example build graph declaration
{
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**"]
},
"test": {
"dependsOn": ["build"],
"outputs": ["coverage/**"]
},
"lint": {
"outputs": []
}
}
}
Code example 2: Calculating affected packages
#!/usr/bin/env bash
set -euo pipefail
BASE=\${1:-origin/main}
pnpm turbo run build test \
--filter="...[\${BASE}]" \
--cache-dir=.turbo/cache \
--summarize
Architecture flow
Tradeoffs
- Graph-based optimization is difficult to set up initially, but significantly reduces long-term CI costs.
- Remote cache is advantageous for speed, but requires cache consistency management.
- The affected-only strategy is efficient, but there is a risk of regression when graphs are missing.
Cleanup
Monorepo performance is determined by graph accuracy rather than build tools. Clear dependency boundaries and default to incremental execution can help you maintain a fast development loop even on large repositories.
Image source
- Cover: source link
- License: CC BY 2.0 / Author: Paul Hudson from United Kingdom
- Note: After downloading the free license image from Wikimedia Commons, it was optimized to JPG at 1600px.