city and CI/CD throughput. Kotlin 2.1 remains viable only when cross-platform code sharing (Android/iOS/desktop) justifies the compile-time tax through significant business logic reuse.
Core Solution
Achieving sub-second incremental feedback and predictable cold builds in 1M+ LOC monorepos requires precise compiler configuration, dependency scoping, and caching architecture.
TypeScript 5.6 Implementation
Leverage TypeScript's mature project reference system and fine-grained type-checking cache. Enable incremental compilation and composite builds to isolate package boundaries and accelerate .d.ts generation.
// tsconfig.base.json
{
"compilerOptions": {
"incremental": true,
"composite": true,
"skipLibCheck": true,
"strict": true
}
}
- Enable
incremental and composite (project references) in all tsconfig.json files to establish dependency graphs and enable parallel type-checking.
- Use
exclude to omit test files, build artifacts, and unused dependencies from compilation scope.
- Set
skipLibCheck: true to bypass type checking of third-party declaration files, reducing cold build overhead by 10β20%.
- Limit
typeRoots to only required type directories to minimize path resolution search space.
Kotlin 2.1 Implementation
Utilize Gradle 8.10 with the Kotlin/JS IR backend. Decompose the monorepo into isolated subprojects to restrict recompilation boundaries and enable Gradle's distributed build cache.
// gradle.properties
org.gradle.caching=true
kotlin.incremental=true
kotlin.js.compiler=ir
- Enable Gradle build cache and Kotlin/JS incremental compilation in
gradle.properties to persist intermediate IR artifacts across CI/CD runs.
- Split large monorepo modules into smaller Gradle subprojects to limit recompilation scope and enable parallel task execution.
- Use the default IR backend (legacy compiler removed in 2.1) for optimized code generation and long-term performance stability.
- Avoid unnecessary
expect/actual declarations if not targeting multiplatform, as they force additional stub resolution and IR mapping overhead.
Framework Compatibility Architecture
TypeScript relies on community-maintained @types packages, introducing negligible compile overhead due to pre-compiled declaration files. Kotlin 2.1 provides first-party wrappers for React/Vue, but third-party npm libraries require Kotlin external declaration generation. Without aggressive caching, this process adds 5β10% to compile times. Pre-generate externals or integrate Gradle's configuration cache to mitigate this latency.
Pitfall Guide
- Ignoring Project References/Composite Builds: Failing to enable
composite in TypeScript or neglecting Gradle subproject boundaries forces full monorepo recompilation on every change, completely negating incremental compilation benefits.
- Overcompiling Test and Artifact Directories: Including test suites, build outputs, or unused dependencies in the compilation scope drastically increases the type-checking surface area. Always use
exclude (TS) or precise source sets (Kotlin/Gradle) to isolate production code.
- Skipping
skipLibCheck in TypeScript: Third-party .d.ts files often contain complex generic constraints and deep recursive types that bloat type-checking time. Disabling skipLibCheck: true can add 10β20 seconds to cold builds without meaningful type safety gains.
- Unnecessary
expect/actual Declarations in Kotlin 2.1: Using multiplatform scaffolding for pure frontend projects forces the compiler to resolve platform-specific stubs and generate additional IR nodes, adding measurable overhead to incremental builds.
- Uncached External Declarations in Kotlin/JS: Relying on on-the-fly generation of Kotlin externals for npm packages without caching adds 5β10% compile time. Pre-generate and commit external declarations or leverage Gradle's configuration cache to persist them.
- Misconfigured
typeRoots Resolution: Allowing TypeScript to scan default node_modules/@types directories in large monorepos causes redundant path resolution and memory allocation. Explicitly limit typeRoots to required directories only.
- Legacy Compiler Fallback in Kotlin 2.1: Kotlin 2.1 removed the legacy Kotlin/JS compiler. Attempting to fallback to it or misconfiguring the IR backend results in suboptimal optimization, broken incremental compilation, and degraded watch-mode performance.
Deliverables
- Monorepo Build Optimization Blueprint: Architecture diagram detailing project reference mapping, Gradle subproject boundaries, CI/CD cache integration strategies, and IR/type-checking pipeline flow for both TypeScript 5.6 and Kotlin 2.1.
- Compile-Time Reduction Checklist: Step-by-step validation matrix covering
tsconfig.json/gradle.properties configurations, including incremental, composite, skipLibCheck, IR backend verification, external declaration caching rules, and CI artifact persistence.
- Configuration Templates: Production-ready
tsconfig.base.json, package-level tsconfig.json, and build.gradle.kts snippets optimized for 100+ package monorepos with strict type checking, watch-mode responsiveness, and zero-redundancy compilation boundaries.