How does Gradle decide whether to publish to a snapshot or a release repository, and what role does the -SNAPSHOT suffix play?
answer
- -SNAPSHOT = mutable / in-dev
- release = immutable
- Gradle doesn't auto-route — you pick URL
- endsWith("SNAPSHOT") ? snapshots : releases
- consumer: changing module, 24h cache
basics
~20 sA version ending in -SNAPSHOT is a snapshot; anything else is a release. Gradle itself doesn't pick the repo — you point publishing at a snapshot or release URL, typically choosing based on whether version ends with -SNAPSHOT.
solid answer
~40 sThe `-SNAPSHOT` suffix is a Maven convention meaning "mutable, in-development version". Repositories treat snapshots specially: they allow re-uploading the same coordinate and often timestamp each upload, whereas release repos are immutable. Gradle's `maven-publish` does **not** auto-route based on the suffix — you declare one or more `repositories { maven { url = ... } }` targets, and you typically pick the URL conditionally: if `version.endsWith("-SNAPSHOT")` use the snapshot URL, else the release URL. Many corporate repos (Nexus/Artifactory) expose separate snapshot and release endpoints precisely so the build chooses by version. On the consumer side, Gradle resolves `-SNAPSHOT` dependencies as changing modules with a 24-hour cache TTL by default. So the suffix drives semantics (mutability, caching) but the routing logic is yours to write.
code
kotlin · 8 linesrepositories {
maven {
url = if (version.toString().endsWith("SNAPSHOT"))
uri("https://repo.acme.com/snapshots")
else
uri("https://repo.acme.com/releases")
}
}go deeper
Know that -SNAPSHOT means in-development/mutable and a plain version means a release.
Explain that you write the snapshot-vs-release URL selection yourself off the version string, plus repo write rules.
Cover consumer-side changing-module caching, reproducibility risks of snapshot deps, and credential handling per endpoint.
Define org-wide promotion policy: who can push releases, snapshot retention, immutability guarantees, and CI gating.
## What a SNAPSHOT version is In the Maven ecosystem a version string ending in `-SNAPSHOT` (e.g. `2.0.0-SNAPSHOT`) is a **mutable, pre-release** identity. It means: "this is the current development state of 2.0.0, and its contents may change without the version string changing." A plain version like `2.0.0` is a **release** — immutable once published. This distinction matters in three places: 1. **Repository write rules.** Snapshot repositories permit overwriting the same coordinate repeatedly (and usually store timestamped sub-versions). Release repositories reject re-publishing an existing coordinate. 2. **Consumer caching.** Gradle treats `-SNAPSHOT` dependencies as *changing modules*: it re-checks the remote up to once every 24 hours by default (`cacheChangingModulesFor`). 3. **Promotion workflow.** Teams develop against `-SNAPSHOT`, then drop the suffix to cut a release. ## Gradle does not auto-route Unlike Maven's `distributionManagement`, Gradle's `maven-publish` plugin will publish a publication to **whatever repository(ies) you declare**. There is no built-in "if snapshot then snapshotRepo" rule. You implement it yourself by choosing the URL based on the version: ```kotlin publishing { publications { create<MavenPublication>("lib") { from(components["java"]) } } repositories { maven { val releases = uri("https://repo.acme.com/releases") val snapshots = uri("https://repo.acme.com/snapshots") url = if (version.toString().endsWith("SNAPSHOT")) snapshots else releases credentials { username = providers.gradleProperty("repoUser").orNull password = providers.gradleProperty("repoPassword").orNull } } } } ``` Because `version` here is `project.version`, the convention is to drive the whole decision off the project version string. ## Why teams keep release and snapshot endpoints separate - Different retention/cleanup policies (snapshots are garbage-collected; releases are kept forever). - Different permissions (anyone can push snapshots; only CI can push releases). - Immutability guarantees for releases so a built artifact never silently changes. ## Gotchas - Forgetting the suffix while iterating means re-pushing to a release repo, which the repo will reject (or, worse, you mutate a "release"). - Mixing snapshot and release dependencies makes builds non-reproducible because the snapshot content can drift between builds.
- On the consumer side, how does Gradle treat a -SNAPSHOT dependency differently?It treats it as a changing module and re-checks the remote at most once per 24 hours by default; you can tune this with resolutionStrategy.cacheChangingModulesFor.
- Why do release repositories reject re-publishing an existing version?Releases are immutable so a coordinate always maps to identical bytes; allowing overwrite would break reproducibility and trust.
- Does maven-publish read the -SNAPSHOT suffix to choose a repository automatically?No. You declare the repositories and write the conditional URL logic yourself based on the version string.
saying these in an interview costs you the question
- Saying Gradle automatically routes snapshots to a snapshot repo like Maven's distributionManagement — it does not.
- Claiming snapshot and release artifacts are equally immutable.