Monorepo CI/CD: Caching, Affected Builds,
and Real Build Times in 2026
Most "use caching" advice skips the measured deltas. This page shows real build time numbers, the three CI strategies for monorepos, and the failure modes that kill cache hit rates.
If total CI bill is the driver: CI/CD cost calculator | CI/CD cost guide
The Three CI Strategies
Benchmark Numbers (Cited to Source)
18% CI build time reduction post-migration
Source: developers.dev aggregate of migration reports
Average across teams that migrated from polyrepo to monorepo with caching enabled. Individual results vary widely based on pre-migration CI setup.
19h (mono) vs 2h (poly) median PR cycle time
Source: Faros AI, 320 engineering teams
PR cycle time measures from first commit to merge. Monorepo PRs are typically larger (touch more packages), which drives the 9x delta. Build time and PR size are confounded.
50-90% build time reduction with remote caching at high hit rates
Source: Nx.dev case studies (vendor-sourced)
Vendor-sourced. Cache hit rates vary by codebase structure, PR size, and how well outputs are defined. Best case: stable packages with deterministic builds. Worst case: large packages with environment-sensitive outputs.
Tool-Specific CI Commands
Common CI Failure Modes in Monorepos
Cache poisoning
HighNon-deterministic build writes wrong artifact to cache. Subsequent runs use poisoned artifact. Fix: ensure build outputs are determined only by inputs (no timestamps, random seeds, env vars not hashed).
Untracked dependencies
HighA build task depends on a file not declared in its input set. Changes to that file don't invalidate the cache. Fix: declare all file inputs explicitly in nx.json inputs or turbo.json inputs.
Cache hit rate collapse
MediumLarge packages or packages with many dependents make almost every PR's cache stale. Fix: split large packages into smaller ones; be explicit about outputs.
Partial-clone issues
Mediumgit clone --depth=1 in CI causes nx affected to fail (no full history to compare against main). Fix: use fetch-depth: 0 or fetch the base branch explicitly.
Flaky tests polluting cache
MediumA flaky test passes and caches its result. Next run returns cached 'pass'. Flakiness hidden by cache. Fix: mark known-flaky tests as no-cache; track flakiness in CI observability.