skip to content

How do you control how long Gradle caches dynamic versions and changing modules, and how do you force a refresh?

level: middleimportance: must knowfreq 55%

answer

  1. cacheDynamicVersionsFor — re-query metadata
  2. cacheChangingModulesFor — re-fetch artifacts
  3. default 24h both
  4. --refresh-dependencies revalidates, doesn't wipe
  5. zero TTL breaks --offline

basics

~10 s

Use resolutionStrategy.cacheDynamicVersionsFor(...) and cacheChangingModulesFor(...) inside a configuration block to set TTLs. To bypass caches for one build, run with --refresh-dependencies.

solid answer

~40 s

Gradle caches dynamic-version resolutions and changing-module artifacts for 24 hours by default. You tune that per build via the resolution strategy: ```kotlin configurations.all { resolutionStrategy { cacheDynamicVersionsFor(10, "minutes") cacheChangingModulesFor(0, "seconds") } } ``` `cacheDynamicVersionsFor` governs how long a resolved selector like `'1.+'` stays pinned before Gradle re-queries repository metadata for newer matches. `cacheChangingModulesFor` governs how long the artifacts behind a changing coordinate (e.g. a `-SNAPSHOT`) are trusted before being re-downloaded. For a one-off forced refresh use the CLI flag `--refresh-dependencies`, which bypasses both caches and re-validates metadata and artifacts against the network. It does not delete the cache; it revalidates. Setting TTLs to zero makes every build hit the network, which hurts performance and offline use, so prefer short windows on CI rather than zero everywhere.

code

kotlin · 7 lines
kotlin
configurations.all {
    resolutionStrategy {
        cacheDynamicVersionsFor(10, "minutes")
        cacheChangingModulesFor(0, "seconds")
    }
}
// one-off: ./gradlew build --refresh-dependencies

go deeper

for a junior

Know the flag --refresh-dependencies exists and that defaults cache for 24h.

for a middle

Name both resolutionStrategy methods correctly and explain what each one re-checks (metadata vs artifacts) plus the unit syntax.

for a senior

Discuss the performance/offline trade-off and steer toward dependency locking for reproducibility; explain --write-locks.

for a principal

Set org defaults: short snapshot windows on CI agents, locking enforced in release pipelines, and a policy for when --refresh-dependencies is acceptable.

## What Gradle caches and why Gradle's dependency cache stores two relevant things for non-static deps: 1. **Resolved dynamic versions** — when `'1.+'` resolves to `1.4.2`, Gradle remembers that mapping so it doesn't re-download and re-parse repository metadata on the next build. 2. **Changing-module artifacts** — the bytes for a `-SNAPSHOT` or `changing=true` coordinate. Both default to a **24-hour** time-to-live. Within the TTL, Gradle uses the cached result without touching the network (great for speed and offline builds); after it, Gradle revalidates. ## The two resolution-strategy knobs These live on a `Configuration`'s `resolutionStrategy`. Apply to one configuration or to all: ```kotlin configurations.all { resolutionStrategy { // re-query metadata for dynamic selectors after 10 minutes cacheDynamicVersionsFor(10, "minutes") // always re-fetch snapshot artifacts cacheChangingModulesFor(0, "seconds") } } ``` Time units accept `"seconds"`, `"minutes"`, `"hours"`, `"days"` (string) or a `java.util.concurrent.TimeUnit`. - `cacheDynamicVersionsFor(0, "seconds")` — every build re-checks for newer matching versions. - `cacheChangingModulesFor(0, "seconds")` — every build re-downloads snapshot artifacts if the remote changed. ## Forcing a refresh on demand The CLI flag bypasses the caches for a single invocation: ```bash ./gradlew build --refresh-dependencies ``` This revalidates cached metadata and artifacts against their source — it does **not** wipe the cache directory. It is the right tool when you suspect a stale snapshot. Avoid baking zero TTLs into the build just to get refresh behaviour; reach for the flag instead, or set short windows scoped to CI. ## Trade-offs and best practice Zero TTLs and `--refresh-dependencies` defeat the cache, slowing builds and breaking `--offline`. They also keep builds non-reproducible. The durable answer for reproducibility is to avoid dynamic/changing inputs in releases and use **dependency locking** so the resolved set is pinned in `gradle.lockfile`. With locking, `--refresh-dependencies` combined with `--write-locks` is how you intentionally advance the pinned versions.

  • Does --refresh-dependencies delete the dependency cache?
    No. It bypasses the TTL and revalidates cached metadata/artifacts against the network for that one build; the cache directory and its contents remain.
  • Why not just set both TTLs to zero project-wide?
    Every build would hit the network, slowing builds, breaking `--offline`, and keeping resolution non-reproducible. Prefer short, CI-scoped windows or dependency locking.
  • How do you advance pinned versions when dependency locking is on?
    Run with `--write-locks` (often together with `--refresh-dependencies`) to re-resolve and rewrite `gradle.lockfile`.

saying these in an interview costs you the question

  • Saying `--refresh-dependencies` clears/deletes the cache.
  • Mixing up the two knobs — using cacheChangingModulesFor to control dynamic version freshness.
  • Recommending zero TTLs as the default without mentioning offline/perf cost.

context