ADR-002: Bazel with staged adoption
Context
A monorepo with Kotlin, TypeScript, Python, and Protobuf requires a build system that handles all languages hermetically. The build system must also support Protobuf code generation as the source of truth for cross-platform contracts.
During MVP (Month 0-6), the team is small and velocity matters more than perfect hermeticity. A staged adoption allows using platform-native tools (Gradle, pnpm, uv) during development while establishing Bazel as the CI and production build system.
Decision
Adopt Bazel 7.5+ as the polyglot build system with staged adoption:
- Phase 1 (MVP): Platform-native tools for inner loop (Gradle for Kotlin, pnpm for TypeScript, uv for Python). Bazel for CI, proto codegen, and production builds.
- Phase 2+: Migrate inner-loop builds to Bazel as the team grows and hermeticity becomes more valuable.
Alternatives considered
| Option | Pros | Cons |
|---|---|---|
| Bazel (chosen) | Polyglot, hermetic, excellent caching, industry standard for large repos | Steep learning curve, complex BUILD files |
| Nx | Great JS/TS support, simpler config, good caching | Weak polyglot support (Kotlin/Python plugins immature) |
| Gradle (multi-project) | Native Kotlin support, mature ecosystem | Poor TypeScript/Python support, not truly polyglot |
| Buck2 | Meta-backed, fast, hermetic | Smaller community, fewer plugins, less documentation |
| Pants | Good Python support, growing Kotlin support | Smaller ecosystem, weaker TypeScript story |
Consequences
What becomes easier
- Proto codegen produces consistent types across all platforms
- CI caching is reliable and reproducible
- Adding new languages/platforms in the future is straightforward
- Production builds are hermetic and deterministic
What becomes harder
- Two build systems to maintain during Phase 1 (Bazel + native)
BUILDfiles need maintenance alongside source code- Developers need to learn Bazel basics