How does Gradle treat Maven -SNAPSHOT dependencies, and how can you make a non-snapshot module behave the same way?
answer
- -SNAPSHOT auto-classified changing
- isChanging = true on a fixed coord
- changing != dynamic
- maven-metadata.xml timestamped artifacts
- TTL still honoured unless set to 0
basics
~20 sGradle automatically treats any version ending in -SNAPSHOT as a changing module — it may re-fetch the artifacts within the cache window. For a non-snapshot coordinate you opt in with isChanging = true on the dependency.
solid answer
~50 sMaven `-SNAPSHOT` versions denote in-development artifacts that get republished. Gradle detects the `-SNAPSHOT` suffix and automatically marks such modules **changing**: the coordinate stays fixed but Gradle will re-resolve the artifacts once the changing-modules cache TTL (default 24h) lapses. For a coordinate that doesn't carry the suffix but whose contents you know can mutate (a nightly build under a fixed tag, a vendored 'latest' artifact), opt in explicitly: ```kotlin dependencies { implementation("org.example:lib:1.0.0") { isChanging = true } } ``` This tells Gradle to apply changing-module caching semantics — i.e. respect `cacheChangingModulesFor` and re-download when stale. Note that `isChanging = true` does NOT make the version dynamic; Gradle still resolves exactly `1.0.0`, it just doesn't trust the cached bytes indefinitely. For Maven snapshots, also be aware that the repository's `maven-metadata.xml` records the unique timestamped snapshot Gradle actually downloads.
code
kotlin · 6 linesdependencies {
implementation("org.example:api:2.0.0-SNAPSHOT") // changing (auto)
implementation("org.example:rolling:1.0.0") {
isChanging = true // changing (forced)
}
}go deeper
Know that -SNAPSHOT means an in-development, mutable dependency.
Explain auto-detection, the isChanging = true opt-in, and that it's about artifact freshness not version selection.
Connect to the changing-modules TTL, maven-metadata.xml timestamping, and reproducibility risks.
Ban snapshots from release builds by policy; if internal snapshots are unavoidable, gate them behind locking and explicit promotion.
## SNAPSHOT in the Maven world A Maven snapshot version like `1.0.0-SNAPSHOT` is a *mutable* coordinate representing the current in-development state of a module. Each deploy publishes a new uniquely-timestamped artifact (e.g. `lib-1.0.0-20260630.120000-7.jar`) and updates the repository's `maven-metadata.xml` to point the `-SNAPSHOT` alias at the latest timestamp. ## How Gradle handles it Gradle recognises the `-SNAPSHOT` suffix and automatically classifies the module as **changing**. Practically: - The version string stays `1.0.0-SNAPSHOT` (it is not dynamic — Gradle is not choosing among versions). - Gradle consults `cacheChangingModulesFor` (default 24h). Within the window it uses cached artifacts; after it, it reads `maven-metadata.xml` and downloads a newer timestamped build if one exists. ## Forcing changing on a fixed coordinate Sometimes a publisher reuses a non-snapshot tag (e.g. a 'rolling' artifact at `:latest` or a fixed release that gets hotfixed in place — bad practice, but it happens). You can apply the same revalidation semantics: ```kotlin dependencies { implementation("org.example:rolling:1.0.0") { isChanging = true } } ``` Groovy equivalent: `implementation('org.example:rolling:1.0.0') { changing = true }`. ## Key distinctions to keep straight - **Changing != dynamic.** Changing affects *artifact freshness* for a fixed coordinate. Dynamic affects *which version* is selected. A `-SNAPSHOT` is changing, not dynamic. - **Caching still applies.** Marking changing doesn't mean 'always re-download'; it means 'this coordinate's bytes can change, so honour the changing-modules TTL'. Combine with `cacheChangingModulesFor(0, "seconds")` for always-fresh. - **Reproducibility cost.** Snapshots make a build's output depend on *when* it ran. For reproducible releases, depend on released (non-snapshot) versions or pin via dependency locking. ```kotlin configurations.all { resolutionStrategy.cacheChangingModulesFor(0, "seconds") } ```
- Does marking a dependency `isChanging = true` change which version is resolved?No. Resolution still targets the exact coordinate; isChanging only affects how long the cached artifacts are trusted before re-download.
- Two snapshot builds ran a day apart and pulled different jars — why?Beyond the 24h changing-modules TTL, Gradle re-read maven-metadata.xml and downloaded a newer timestamped snapshot artifact published in the meantime.
saying these in an interview costs you the question
- Calling a -SNAPSHOT a dynamic version.
- Thinking isChanging changes version selection.
- Assuming changing means 'download every build' regardless of TTL.