What are the classpath and caching tradeoffs between buildSrc and an included build-logic build?
answer
- buildSrc: global script classpath, zero wiring
- buildSrc change → broad config-cache invalidation
- build-logic: by-id, opt-in, isolated
- build-logic: narrower invalidation, more setup
- small→buildSrc, large/shared→build-logic
basics
~20 sbuildSrc adds its jar to every build script's classpath (simple but global, and changes invalidate broadly). build-logic is consumed by id only where applied, giving narrower caching impact and explicit dependencies, at the cost of more setup.
solid answer
~40 sWith `buildSrc`, Gradle compiles it automatically and exposes its classes on the **build-script classpath of every project** — convenient, zero wiring, but the dependency is implicit and global, and because that classpath participates in build-script compilation and the configuration-cache key, a buildSrc change tends to invalidate configuration-time caching across the build. With `build-logic`, you pay setup cost (its own `settings.gradle.kts`, `includeBuild`, plugin projects) but get **by-id, opt-in consumption**: only subprojects that apply a plugin depend on it, so a change to one convention plugin recompiles that plugin and reconfigures only its consumers. The tradeoff is convenience and low ceremony (buildSrc) versus isolation, explicit dependencies, testability/publishability, and finer cache invalidation (build-logic). For small builds buildSrc is fine; as the build grows or you split conventions into modules, build-logic's caching and isolation benefits win.
go deeper
buildSrc is automatic and global; build-logic is opt-in by id. Know that much.
Articulate the classpath difference (global vs by-id) and the broad-vs-narrow cache invalidation tradeoff plus build-logic's setup cost.
Quantify when the migration pays off and tie classpath-as-cache-key to invalidation behavior.
Set org guidance on when teams should adopt build-logic versus buildSrc based on measured config-cache churn and reuse needs.
## buildSrc classpath model `buildSrc` is compiled into a single jar that Gradle injects onto the **build-script classpath** of every project in the build. Pros: nothing to wire, every script can reference the helpers and convention plugins immediately. Cons: - **Implicit/global dependency.** No `plugins {}` or `dependencies {}` entry shows the coupling; everything sees everything. - **Broad cache invalidation.** That classpath is part of what's hashed for build-script compilation and the **configuration cache**, so editing buildSrc changes the key for all scripts and invalidates configuration-time caching widely. (Modern Gradle has softened this, but the structural effect remains.) - **One monolith.** You can't expose a subset of helpers to a subset of projects. ## build-logic classpath model `build-logic` is a separate build whose plugin projects are consumed **by plugin id**, only where applied: - **Explicit, opt-in dependency.** A subproject depends on a convention plugin only by applying its id, so the graph is visible and minimal. - **Narrower invalidation.** Editing one plugin recompiles that plugin project and reconfigures only the subprojects that apply it; unrelated subprojects keep their configuration-cache entries. - **Isolated dependencies.** Each plugin project keeps its own dependencies behind a classloading boundary instead of merging onto a shared classpath. ## The cost side build-logic is more ceremony: a second settings file, an `includeBuild` line, plugin-project structure, and plugins consumed by id rather than 'just being there'. For a tiny single-module build that overhead can outweigh the benefit. ## Picking ```text Small/simple build, few conventions -> buildSrc (low ceremony) Large build, multiple convention groups -> build-logic (isolation + finer caching) Need to test/publish/share conventions -> build-logic ``` Many teams start with buildSrc and migrate to build-logic when convention logic grows, configuration-cache churn becomes noticeable, or conventions must be reused across repos.
- Why is buildSrc 'zero wiring' but build-logic isn't?buildSrc is auto-detected by name and auto-injected onto every script classpath; build-logic needs its own settings.gradle.kts and an includeBuild declaration plus by-id application.
- What's the caching downside of buildSrc?Its jar is part of the build-script/configuration-cache key for every script, so editing it tends to invalidate configuration-time caching broadly rather than just for affected subprojects.
saying these in an interview costs you the question
- Saying build-logic is strictly better with no downsides — it adds real setup/ceremony.
- Claiming buildSrc has no caching at all — it caches, but invalidates broadly on change.