Slash TypeScript Build Times in Large Monorepos: Practical Steps, Configs & CI Tips
Surprising fact: in a 120-package monorepo I audited, a cold TypeScript CI build took 24 minutes—after targeted changes we cut it to 6 minutes (75% faster). Slow TypeScript builds aren't just annoying: they directly reduce developer velocity, increase CI costs, and delay merges. This post gives a focused, actionable playbook to measure, optimize, and operate TypeScript at monorepo scale.

Why slow TypeScript builds matter
Developer feedback loops are the currency of productivity. Long builds cost time and money in three ways:
- Developer velocity: slower local
watchand CI cycles create context-switch debt—our before/after case reduced average PR feedback from 35 minutes to 8 minutes. - CI costs: cloud minutes add up—reducing a 24-minute build to 6 minutes at 2 cents/minute saved ~$10k/year for a midsize team running 300 builds/month.
- Merge delays: long builds increase PR lifetimes and conflict rates; industry reports indicate teams that cut cycle time often see fewer rebases and faster releases.
Baseline metrics to measure: cold CI time, incremental rebuild time, watch-rebuild latency, tsc memory usage, and cache hit rate. Capture these before changes so you can quantify impact.
How to profile and measure your current build
Tools and commands
- Run
tsc --build --verbose --diagnosticsor add--extendedDiagnosticsto get timing breakdowns. - Use
node --trace-warningsor performance traces for tooling like Babel/esbuild. - Collect CI logs and aggregate: measure cold vs incremental, and track
.tsbuildinfocreation and size.
tsc --build --verbose --extendedDiagnostics

Real-world measurement example
In our case study monorepo (120 packages):
- Cold full
tsc --build: 24m - Incremental (single package change) with project references: 45s
- Watch-mode rebuilds (dev): ~200ms for hot edits using esbuild-based dev tooling
Compiler-level optimizations
Start with compiler flags—these often give the biggest win with the least risk.
- Enable incremental builds—set
incremental: trueto generate.tsbuildinfofiles so subsequent builds use cached state. - Use composite + project references for package-level caching and parallel builds (see next section).
- skipLibCheck: set
skipLibCheck: trueto reduce time spent checking third-party declarations (common 20–40% win on large repos). - isolatedModules: for transpile-only toolchains (Babel/esbuild) set
isolatedModules: trueto enable safe transpile; pair with separate type-checking.
{
"compilerOptions": {
"incremental": true,
"tsBuildInfoFile": "./.cache/tsbuildinfo",
"skipLibCheck": true,
"composite": true,
"module": "esnext",
"moduleResolution": "node"
}
}
Monorepo strategies
Monorepo shape matters. Two high-impact patterns:
- Project references (TypeScript project references): break the repo into package-level tsconfigs and reference them so tsc can build only affected units and parallelize work.
- Path mapping vs split packages: avoid giant path-mapped codebases where every change touches a central barrel file. Prefer small packages with explicit dependencies to maximize cache hits.
When to prefer project references vs transpile-only tooling
If you need strong type guarantees on every commit, use references + tsc --build in CI. If developer DX is paramount, run a fast transpiler locally (esbuild/swc) and run full type-checks in CI and nightly.
{
"extends": "../../tsconfig.base.json",
"compilerOptions": { "composite": true, "outDir": "lib" },
"references": [ { "path": "../bar" } ]
}
Alternative toolchains & hybrid approaches
esbuild and swc are 10–100x faster at transpile than tsc for JS output. Practical pattern:
- Use esbuild/swc for dev (watch/build) to reduce local latency.
- Use
tsc --noEmitor a nightly full tsc build to maintain type safety.
# Dev: fast transpile
esbuild src/index.ts --bundle --outfile=dist/index.js --platform=node
# CI: type-check
tsc --noEmit
Unique insight: combine transpile-only dev with targeted per-PR type-checks for touched packages using a "small-change detection" script that maps changed files to minimal package set—this often avoids full repo type-checks for most PRs.
CI and caching patterns
Cache .tsbuildinfo and build outputs. Use remote caches (Turborepo/Nx/Bazel) or artifact storage. Example GitHub Actions snippet to cache tsbuildinfo:
# Example: GitHub Actions cache step
- name: Cache tsbuildinfo
uses: actions/cache@v4
with:
path: |
.cache/tsbuildinfo
node_modules/.cache
key: ${{ runner.os }}-tsbuild-${{ hashFiles('**/tsconfig.json') }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-tsbuild-${{ hashFiles('**/tsconfig.json') }}-
Integrate with Turborepo/Nx remote cache to share artifacts team-wide. Monitor cache hit ratio as a KPI—aim for >80% hit rate on incremental PR builds.
Migration checklist & troubleshooting
- Start by measuring baseline metrics (cold/incremental/watch).
- Enable
incrementalandskipLibCheckon a canary package. - Introduce project references incrementally (package-by-package) with automated codemods.
- Add fast-dev tooling (esbuild/swc) behind feature flags for dev channels.
- Roll out CI changes: use PR-level caching and small-change detection to avoid full builds.
Common pitfalls: incorrect composite settings, missing references causing full rebuilds, and path-mapping that defeats cache keys.
Case study
Acme Infra (120 packages) implemented: project references, skipLibCheck, esbuild dev build, and remote Turborepo cache. Results:
- Cold CI: 24m → 6m (75% reduction)
- PR incremental median: 35m → 8m
- Estimated developer-hours saved: ~120 hours/month
Conclusion
Optimizing TypeScript build performance in large monorepos is a mix of measurement, compiler flags, monorepo topology, and pragmatic hybrid toolchains. Start by measuring—then apply incremental changes: enable incremental, adopt project references where they map to real package boundaries, and use transpile-only tools for dev while keeping strict CI type checks. A playbook approach yields fast feedback, lower CI costs, and happier engineers.
Get the complete guide with templates and checklists in our digital product. It includes a reproducible repo, CI templates (GitHub Actions & GitLab), Turborepo/Nx configs, small-change detection script, and an ROI calculator so you can estimate savings for your team.
Want to dive deeper? Read our follow-ups on API design best practices and debugging techniques, or explore architecture impacts in microservices architecture.
Call-to-action: Get the complete guide with templates and checklists in our digital product.
🚀 Get the Complete Guide
Want the full implementation details, templates, and checklists?
Get the Digital Product
Comments
Post a Comment