skip to content

Repositories and Metadata

Where Gradle looks for modules and what it reads when it finds them: repository declarations, filtering and credentials, Gradle Module Metadata, variant matching, metadata rules, and the local cache. Interviewers ask because this metadata model is where Gradle diverges most from Maven.

on this pageshow

explore

questions

page 1 of 2

Where does Gradle store downloaded dependencies, and what is the purpose of that cache?

level: juniorimportance: must knowfreq 60%

answer

  1. GRADLE_USER_HOME/caches/modules-2
  2. default ~/.gradle
  3. global, shared across projects + versions
  4. metadata + artifacts stored separately
  5. not the build cache

basics

~10 s

Gradle stores downloaded artifacts and metadata under GRADLE_USER_HOME/caches/modules-2 (default ~/.gradle). The cache avoids re-downloading the same dependency on every build, speeding things up and enabling offline reuse.

solid answer

~40 s

Resolved dependencies live in the **global dependency cache** at `GRADLE_USER_HOME/caches/modules-2` (default `~/.gradle`, overridable via the `GRADLE_USER_HOME` env var or `-g`). It is shared across **all** projects and Gradle versions on the machine, so an artifact downloaded once is reused everywhere. The cache stores both the binary artifacts (jars, etc.) and the resolved metadata (POMs, Gradle Module Metadata) separately, keyed by module coordinates and content hashes. Gradle uses SHA checksums and a local file lock so concurrent builds can safely share it. Because it is global, it is not part of any project directory and should not be checked into version control. Clearing it (deleting the folder) forces a full re-download on the next build.

code

bash · 8 lines
bash
# Default cache location
ls ~/.gradle/caches/modules-2/files-2.1/

# Override GRADLE_USER_HOME (e.g. on CI)
export GRADLE_USER_HOME=/ci/.gradle
./gradlew build
# or per-invocation:
./gradlew -g /ci/.gradle build

go deeper

for a junior

Know the default path (~/.gradle / caches/modules-2) and that it avoids re-downloading.

for a middle

Explain GRADLE_USER_HOME override, global sharing across projects/versions, and metadata-vs-artifact separation.

for a senior

Discuss concurrency safety, checksums, and why it shouldn't be in VCS but should be a CI cache layer.

for a principal

Frame cache strategy across a CI fleet: shared/seeded GRADLE_USER_HOME, restore keys, and isolation tradeoffs vs. cache poisoning.

## What the dependency cache is When Gradle resolves a configuration, it must obtain two things for every module: the **metadata** (which describes the module's coordinates, dependencies, and variants — a Maven POM or a Gradle Module Metadata file) and the **artifacts** (the actual jars/aars/zips). Downloading these from a remote repository on every build would be slow, so Gradle keeps a persistent local copy in the **dependency cache**. ## Where it lives The cache sits under **`GRADLE_USER_HOME`**, which defaults to **`~/.gradle`** (`%USERPROFILE%\.gradle` on Windows). The dependency cache specifically is **`GRADLE_USER_HOME/caches/modules-2`**. You can move `GRADLE_USER_HOME` with the environment variable of the same name or the `--gradle-user-home`/`-g` command-line flag. Key properties: - **Global / shared.** It is not per-project. Every build on the machine, regardless of Gradle version, reads and writes the same `modules-2` directory. A jar fetched by project A is reused by project B for free. - **Metadata and artifacts are stored separately**, each keyed by module coordinates plus a content hash, so identical content is deduplicated. - **Concurrency-safe.** Gradle uses checksums and file locks so multiple builds (even parallel ones) can share the cache without corruption. - **Not VCS material.** Because it is large, machine-local, and reproducible, you never commit it. ## Why it matters The cache is what makes warm builds fast and is the foundation for **offline builds** (`--offline`) — if everything you need is already cached, you can build with no network at all. It also underpins reproducibility: once resolved, the same versions are reused until you explicitly refresh. ```bash # Inspect the cache layout ls ~/.gradle/caches/modules-2/files-2.1/ # Move the cache for CI GRADLE_USER_HOME=/ci/gradle-home ./gradlew build ``` Do not confuse this with the **build cache** (`caches/build-cache-1`, task outputs) or per-project `.gradle/` directories — those are different mechanisms.

  • Should the dependency cache be committed to version control?
    No. It is machine-local, large, and fully reproducible from the repositories. Commit it and you bloat the repo and risk stale/incompatible binaries. On CI you instead persist/restore GRADLE_USER_HOME as a CI cache layer.
  • How is the dependency cache different from the build cache?
    The dependency cache (caches/modules-2) stores downloaded external artifacts and metadata. The build cache (caches/build-cache-1, or a remote build cache) stores reusable outputs of @CacheableTask tasks (compilation, etc.). Different keys, different purpose.

saying these in an interview costs you the question

  • Saying dependencies are cached inside the project's .gradle/ directory (that holds per-project incremental state, not the shared artifact cache).
  • Confusing the dependency cache with the build cache.
  • Claiming the cache is per-Gradle-version isolated — modules-2 is shared across versions.

context

open as a page

What is centralized repository management in Gradle, and where do you configure it?

level: juniorimportance: must knowfreq 55%

basics

~10 s

It's declaring repositories once for the whole build inside settings.gradle.kts using dependencyResolutionManagement { repositories {} }, instead of repeating repositories {} in every project's build.gradle.kts.

open as a page

What is repository content filtering in Gradle, and why would you use it?

level: juniorimportance: must knowfreq 55%

basics

~10 s

It tells Gradle which repositories can or cannot supply which modules, using a content {} block with includeGroup/excludeGroup. This avoids pointless lookups and speeds up resolution.

open as a page

How do you configure a private Maven repository in Gradle that requires a username and password, and where should those secrets actually live?

level: juniorimportance: must knowfreq 70%

basics

~10 s

Declare the repo with a url and a credentials { username; password } block. Don't hardcode the secrets — read them from gradle.properties or environment variables instead.

open as a page

What is a repository in Gradle, and how do you declare one so your dependencies can be resolved?

level: juniorimportance: must knowfreq 78%

basics

~10 s

A repository is a source Gradle downloads dependency artifacts and metadata from. You declare them in a repositories {} block, e.g. mavenCentral(), so Gradle knows where to look for the modules you depend on.

open as a page

What does running Gradle with --offline do, and what are the prerequisites for it to succeed?

level: middleimportance: must knowfreq 45%

basics

~10 s

--offline tells Gradle never to access the network during a build; it resolves everything from the dependency cache. It only succeeds if every required metadata and artifact is already cached, otherwise the build fails.

open as a page

What does the --refresh-dependencies flag do, and when would you use it?

level: middleimportance: must knowfreq 55%

basics

~10 s

--refresh-dependencies tells Gradle to ignore cached metadata TTLs and re-check every dependency against the repositories, re-downloading metadata and any changed artifacts. Use it when a SNAPSHOT or dynamic version seems stale.

open as a page

What does RepositoriesMode.FAIL_ON_PROJECT_REPOS do, and why would you set it?

level: middleimportance: must knowfreq 50%

basics

~10 s

It makes the build fail if any subproject declares its own repositories {} block, forcing all repositories to come from the central settings.gradle.kts list — making that list the single source of truth.

open as a page

Explain how includeGroup, includeGroupByRegex, and excludeGroup combine within a repository's content block. What is the precedence?

level: middleimportance: must knowfreq 45%

basics

~10 s

Any include* rule flips the repo to allowlist mode — only matching coordinates are served. exclude* rules then subtract from what remains. With no rules at all, the repo serves everything.

open as a page

How does the order of declared repositories affect dependency resolution in Gradle?

level: middleimportance: must knowfreq 70%

basics

~20 s

Gradle searches repositories in the order you declare them and stops at the first one that has the module's metadata. So order determines which source wins when a module exists in more than one repo.

open as a page

Show how a Component Metadata Rule adds or removes dependencies on a published module with a broken POM.

level: middleimportance: must knowfreq 38%

basics

~20 s

In the rule, call details.allVariants { withDependencies { add("g:a:v") } } to add a missing dependency, or removeAll { it.group == "bad" } to drop a bogus one — patching the module's dependency list at resolution time.

open as a page

What is a Component Metadata Rule in Gradle, and why would you use one?

level: middleimportance: must knowfreq 55%

basics

~20 s

A rule that lets you fix or enrich a published dependency's metadata (its POM/Gradle Module Metadata) at resolution time — without forking the artifact. You register it in the components block to patch wrong or missing info.

open as a page

What is Gradle Module Metadata (the .module file), and how does it differ from a Maven POM?

level: middleimportance: must knowfreq 55%

basics

~20 s

Gradle Module Metadata is a JSON file (the .module file) published next to the POM/Ivy file. Unlike a POM, it can describe multiple variants of a component, each with its own dependencies, attributes, and artifacts.

open as a page

What does it mean that Gradle's dependency resolution is 'variant-aware', and how does it differ from Maven's model?

level: middleimportance: must knowfreq 55%

basics

~20 s

A component (like a library) publishes several variants — e.g. an API jar, a runtime jar, sources, javadoc. Gradle picks the right one by matching attributes (Usage, Category, etc.) to what the consumer asks for, instead of using one fixed jar like Maven.

open as a page

How is the .module file produced and published, and how do you enable or disable Gradle Module Metadata publication?

level: juniorimportance: should knowfreq 30%

basics

~20 s

The maven-publish (or ivy-publish) plugin generates the .module file automatically and publishes it with your POM and jars. GMM publication is on by default; you can toggle it via tasks.withType<GenerateModuleMetadata>().configureEach { enabled = ... }.

open as a page

After switching to FAIL_ON_PROJECT_REPOS, a previously-working module fails resolution for a dependency it used to download fine. What likely happened and how do you fix it?

level: middleimportance: should knowfreq 30%

basics

~20 s

That module had its own repositories {} block providing a repo not in the central list. Strict mode disables/forbids project repos, so the dependency can't be found. Fix: add that repository to the central dependencyResolutionManagement block.

open as a page

How does exclusiveContent {} differ from a per-repository content {} block, and when would you choose it?

level: middleimportance: should knowfreq 35%

basics

~20 s

content {} only describes one repo; you'd still have to exclude the same group everywhere else. exclusiveContent {} declares a group is served by exactly one repo and auto-excludes it from all others in one place.

open as a page

Give a realistic example of using content filtering to separate snapshot/internal modules from a public mirror, and explain how it improves resolution performance.

level: middleimportance: should knowfreq 20%

basics

~10 s

Route internal/snapshot groups to your private repo with includeGroup, and excludeGroup them from the public mirror. Gradle then skips the public repo for those modules, removing dead lookups and 404s, so resolution is faster.

open as a page

Some private repositories authenticate with a token in an HTTP header rather than basic auth. How do you configure that in Gradle?

level: middleimportance: should knowfreq 45%

basics

~10 s

Use credentials(HttpHeaderCredentials::class) to set a header name and value (e.g. a bearer token), then declare authentication { create<HttpHeaderAuthentication>("header") } so Gradle sends that header.

open as a page

How do you declare a custom Maven repository and an Ivy repository in Gradle, and when would you reach for `flatDir`?

level: middleimportance: should knowfreq 50%

basics

~20 s

Use maven { url = uri("https://...") } for a Maven-layout server and ivy { url = uri("...") } (often with a patternLayout) for an Ivy-layout server. flatDir { dirs("libs") } points at a folder of bare JARs with no metadata — a last resort.

open as a page

What does `mavenLocal()` do in a Gradle build, and why is it discouraged by default?

level: middleimportance: should knowfreq 55%

basics

~10 s

mavenLocal() adds your ~/.m2/repository directory as a repository. It's discouraged because that directory is a mutable, machine-local Maven cache, so it makes builds non-reproducible across machines and can serve unexpected artifacts.

open as a page

What is the difference between `components.withModule(...)` and `components.all(...)`, and when would you choose each?

level: middleimportance: should knowfreq 40%

basics

~10 s

withModule("group:name", Rule) runs the rule only for that one module. all(Rule) runs it for every resolved module. Prefer withModule when you know the target; use all only for broad, cheap, generic patches.

open as a page

How does the `metadataSources { }` block on a repository control which metadata Gradle reads, and when would you change it?

level: middleimportance: should knowfreq 40%

basics

~10 s

Inside a repository's metadataSources { } block you list which descriptors Gradle should look for — gradleMetadata(), mavenPom(), ignoreGradleMetadataRedirection(), or artifact(). Gradle tries them in the order declared.

open as a page

A build fails with 'No matching variant ... was found' or 'cannot choose between variants'. How do you diagnose and fix it?

level: middleimportance: should knowfreq 45%

basics

~20 s

Read the error: it lists the attributes you requested versus what each variant offers, marking matches and mismatches. Fix by aligning attributes — request the right Usage/JVM version, or add a compatibility/disambiguation rule so one variant is selected.

open as a page

How does the TargetJvmVersion attribute drive variant selection for libraries that support multiple JVM targets?

level: middleimportance: should knowfreq 40%

basics

~20 s

Each variant declares the JVM version it targets via TargetJvmVersion. A variant built for an older JVM is compatible with a consumer on a newer one, and Gradle picks the highest compatible version for your build.

open as a page

How does Gradle decide when a cached SNAPSHOT or dynamic version is stale, and how can you control that freshness window?

level: seniorimportance: should knowfreq 35%

basics

~10 s

Gradle caches changing modules (SNAPSHOTs) and dynamic version listings with a time-to-live, 24 hours by default. You tune it per-configuration with resolutionStrategy.cacheChangingModulesFor and cacheDynamicVersionsFor, or override once with --refresh-dependencies.

open as a page

Compare PREFER_PROJECT, PREFER_SETTINGS, and FAIL_ON_PROJECT_REPOS. When would you choose each during a migration?

level: seniorimportance: should knowfreq 35%

basics

~10 s

PREFER_PROJECT (default) lets project repos override central; PREFER_SETTINGS uses central and ignores project repos; FAIL_ON_PROJECT_REPOS fails if any project declares repos. Use PREFER_SETTINGS mid-migration, then FAIL_ON_PROJECT_REPOS once clean.

open as a page

A team centralizes dependency repositories with FAIL_ON_PROJECT_REPOS, but their convention plugin still needs a special repository for plugins. Where does that go, and why doesn't the strict mode affect it?

level: seniorimportance: should knowfreq 25%

basics

~10 s

Plugin repositories go in pluginManagement { repositories {} } in settings.gradle.kts. dependencyResolutionManagement and its repositoriesMode only govern regular dependency repositories, so FAIL_ON_PROJECT_REPOS doesn't touch plugin resolution.

open as a page

Where can repository content filtering be declared, and how does it interact with centralized dependencyResolutionManagement and pluginManagement?

level: seniorimportance: should knowfreq 25%

basics

~10 s

The same content {}/exclusiveContent {} API works in a project's repositories {}, in settings.gradle under dependencyResolutionManagement.repositories {}, and in pluginManagement.repositories {} for plugin resolution. Settings-level filtering applies project-wide.

open as a page

How do you supply private-repository credentials in CI without committing secrets, and how do you keep them from leaking into build logs or the cache?

level: seniorimportance: should knowfreq 40%

basics

~10 s

Inject credentials as ORG_GRADLE_PROJECT_<name>Username/Password environment variables from the CI secret store. Keep them out of the repo, never echo them, and let Gradle treat them as credentials so they aren't printed.

open as a page

showing 1–30 of 42