How a 300-Engineer Monorepo Cut CI Time by 78% with Remote Caching and Affected-Only Builds
A fast-growing SaaS platform tamed a sprawling monorepo by combining Nx remote caching with affected-graph builds, slashing median CI from 47 min to 10 min and saving $180k/year in compute.
CI/CD & Delivery · advanced · 12 min read · 2411 words · By Sandip Das · Published
Composite scenario: built from common industry patterns; the figures are illustrative.
What this covers
- The Situation
- The Problem
- Constraints
- Options Considered
- The Solution
- Implementation
- Results
- What Went Wrong Along the Way
- Lessons Learned
- Apply It Yourself
Key numbers
| Metric | Before | After |
|---|---|---|
| Median CI wall-clock time per PR | 47 min | 10 min |
| Annual CI compute cost | ~$230k | ~$51k |
| Remote cache hit rate | 0% | 74% |
| Merge-train incidents per month | 8–12 | 0–1 |
| Engineer context switches per PR cycle | 2.3 | 0.6 |
Key components
- Nx Affected Graph — Computes the minimal set of projects touched by a PR diff, eliminating unnecessary rebuilds.
- S3 Remote Cache Bucket — Stores content-addressed task outputs so any runner can replay a prior result without re-executing the task.
- Cache Router (Nx task runner plugin) — Checks local disk then remote S3 before deciding whether to execute or restore a cached task output.
- CI Metrics Postgres DB — Captures per-task timing and cache-status events to enable data-driven tuning of the cache strategy.
- Grafana Dashboard — Surfaces cache hit rate, median duration, and per-project build frequency for continuous observability.
- GitHub Actions OIDC + IAM Role — Grants runners short-lived, least-privilege access to the S3 cache bucket without storing long-lived credentials.
The Situation
This is a composite scenario assembled from patterns observed across multiple engineering organisations; all figures are illustrative and chosen to be internally consistent, not to represent any single company.
The organisation in question is a B2B SaaS platform serving mid-market financial-services clients. At the time of the events described, roughly 300 engineers worked across 18 product squads, all committing into a single Git monorepo that had grown organically over six years. The repo contained approximately 140 deployable units: Node.js and Go microservices, a React design-system library, a shared TypeScript SDK, a handful of Python data-pipeline workers, and a suite of Terraform modules. Build tooling was Nx 16 (for JavaScript/TypeScript projects) with a thin shell-script wrapper that invoked Go and Python toolchains for the non-JS packages. CI ran on GitHub Actions with a pool of ubuntu-22.04 runners—a mix of GitHub-hosted 4-core machines and self-hosted 16-core bare-metal boxes in a co-location facility.
The platform processed roughly 4 million API calls per day and had a 99.9% SLA commitment. The engineering organisation had adopted a trunk-based development model, meaning every engineer merged to main at least once per day. At peak, the repo received 180–220 pull requests per day.
---
The rest of this case study — the trade-offs, the scaling numbers and the build prompt — is available to LearnXops members. Create an account or see membership.
Topics: ci-cd, monorepo, nx, remote-caching, turborepo, build-optimization
Related case studies
- How a B2B SaaS Platform Migrated 200 Services to GitOps with Argo CD
- How a B2B SaaS Team Cut CI Pipeline Time from 45 Minutes to 8
- How a B2B SaaS Team Cut Failed Deployments by 80% with Canary Releases and SLO-Driven Rollback
- Knight Capital 2012: How an Incomplete Deployment and a Reused Flag Lost $460 Million in 45 Minutes
- The Cloudflare July 2019 Outage: How One Regex Took Down a Global CDN
- The Cloudflare November 2025 Outage: How a Database Permission Change Broke Global Proxy Traffic