Technology Trends

Version Catalogs and Convention Plugins: The Build Configuration Pattern Every Multi-Module Android Team Needs

Strategia-X EditorialApr 4, 20268 min read950 words

The Multi-Module Build Configuration Problem

Every Android project that grows beyond a single module hits duplicated build configuration. Module after module declares the same compileSdk, Kotlin version, testing dependencies, and proguard rules. Developers copy a working build.gradle.kts, tweak module-specific parts, and move on. Within months, 15 modules have 15 slightly different build files with dependency version drift, inconsistent compile options, and cognitive overhead that makes build maintenance a dreaded chore.

Version Catalogs: Single Source of Truth

A Gradle version catalog (gradle/libs.versions.toml) declares all dependency coordinates in one TOML file. Modules reference them through generated type-safe accessors: instead of hardcoding group:artifact:version strings, you write libs.androidx.core.ktx. Versions are declared once, typos become compile-time errors, and IDE autocompletion makes dependencies discoverable. Bundles group commonly-used libraries (Compose UI + Material 3 + tooling) for one-line application. On a 15-module project, dependency version drift becomes impossible.

Convention Plugins: Extracting Shared Build Logic

Convention plugins solve everything version catalogs don't: compileSdk, minSdk, Kotlin compiler options, Compose configuration, test runner setup, proguard rules. Defined in a build-logic module as Kotlin classes implementing Plugin<Project>, each plugin configures one concern. Layer them: AndroidLibraryConventionPlugin handles SDK targets, ComposeConventionPlugin handles Compose compiler, HiltConventionPlugin handles DI setup. Feature modules compose only the plugins they need. Because the build-logic module is a regular Kotlin project, you get full IDE support and can write unit tests for build configuration.

The Result: 10-Line Feature Module Build Files

With both patterns in place, a new feature module's build.gradle.kts contains plugin applications and module-specific dependencies — roughly 10 lines instead of 80. Updating compileSdk changes one file instead of 15. Adding a Compose compiler option changes one file. New module creation cannot accidentally forget settings because decisions are encoded in convention plugins, not left to individual authors. The first time a Kotlin version bump changes one file instead of fifteen, the infrastructure pays for itself.

Incremental Migration Strategy

Adoption is incremental: Phase 1 creates the TOML catalog and migrates dependencies one module at a time. Phase 2 creates the build-logic module with one convention plugin, proving the infrastructure on a single module. Phase 3 expands convention plugins for Compose, Hilt, and testing. Phase 4 adds CI checks that reject direct compileSdk settings. The entire migration takes 2-4 weeks for a 15-module project without blocking feature work. Each phase is independently valuable and mergeable.

android development gradle build tools multi-module convention plugins developer experience

— Rocky

#androiddevelopment#gradle#buildtools#multi-module#conventionplugins#developerexperience#IndieDeveloper#BuildInPublic#EngineeringDreams#StrategiaX