skip to content

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%

answer

  1. mirror excludeGroup internal
  2. private repo includeGroup internal
  3. skip dead 404 lookups
  4. snapshot churn isolated
  5. complements cache TTL tuning

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.

solid answer

~40 s

A common setup has a fast public mirror (e.g. an internal proxy of Maven Central) plus a private repo for in-house snapshots. Without filtering, every internal `com.acme` request first probes the mirror, gets a 404, then tries the private repo — wasted round-trips on every build, multiplied across modules and made worse by snapshots, which re-check metadata frequently and may use shorter cache TTLs. With filtering, you `excludeGroup("com.acme")` on the mirror and `includeGroup("com.acme")` on the private repo (or use `exclusiveContent`). Now `com.acme` requests go straight to the private repo and public requests never touch it. The performance win is fewer HTTP requests and no dead-end 404 latency; it compounds with `--refresh-dependencies` and CI where caches are cold. It also keeps snapshot churn isolated to the repo that actually holds them.

code

kotlin · 12 lines
kotlin
repositories {
    maven {
        name = "central-mirror"
        url = uri("https://mirror.mycompany.com/central")
        content { excludeGroupByRegex("com\\.acme\\..*") }
    }
    maven {
        name = "internal-snapshots"
        url = uri("https://repo.mycompany.com/snapshots")
        content { includeGroupByRegex("com\\.acme\\..*") }
    }
}

go deeper

for a junior

Show a basic include/exclude split and state it avoids wasted lookups.

for a middle

Explain the 404 round-trip cost, snapshot churn isolation, and that filtering is separate from cache TTL tuning.

for a senior

Quantify the multi-module / CI cold-cache impact and combine with cache strategy and exclusiveContent.

for a principal

Standardize mirror+internal split with settings-level filters as part of build-performance and supply-chain policy.

## Scenario You have: - `https://mirror.mycompany.com/central` — a proxy/mirror of Maven Central (public, third-party deps). - `https://repo.mycompany.com/snapshots` — your internal snapshot/release repo for `com.acme.*`. ### Without filtering Gradle searches in declaration order. For `com.acme.payments:api:1.2.0-SNAPSHOT` it hits the mirror first → 404 → then the snapshot repo → hit. For a third-party `org.apache.commons:commons-lang3` it hits the mirror → hit. Every internal coordinate pays a 404 round-trip against the mirror, and SNAPSHOT metadata (`maven-metadata.xml`) is re-fetched more often because snapshots are mutable and cached with short TTLs. ### With filtering ```kotlin repositories { maven { name = "central-mirror" url = uri("https://mirror.mycompany.com/central") content { excludeGroupByRegex("com\\.acme\\..*") } } maven { name = "internal-snapshots" url = uri("https://repo.mycompany.com/snapshots") content { includeGroupByRegex("com\\.acme\\..*") } } } ``` Now: - `com.acme.*` → only `internal-snapshots` is a candidate; the mirror is skipped entirely. - `org.apache.*`, `org.springframework.*` → only the mirror is a candidate; the snapshot repo is skipped. ## Why it is faster 1. **Fewer HTTP round-trips:** each module is queried against one repo, not all of them. Pre-network filtering means Gradle doesn't even open a connection to a non-candidate repo. 2. **No dead-end 404s:** 404 responses still cost a full request/response; eliminating them removes real latency, especially over a slow link or in CI. 3. **Snapshot churn isolation:** snapshot metadata re-validation is confined to the repo that holds snapshots, so public-dep resolution isn't slowed by snapshot TTL behavior. 4. **Scales with module count:** in a multi-module build the savings multiply. ## Note on dynamic/snapshot versions Filtering changes *which repos are queried*, not caching of dynamic/changing versions — that's controlled by `ResolutionStrategy.cacheChangingModulesFor`/`cacheDynamicVersionsFor`. The two are complementary: filtering reduces where Gradle looks; cache tuning reduces how often it re-checks.

  • Does content filtering control how long snapshot metadata is cached?
    No. Caching of changing/dynamic versions is controlled by ResolutionStrategy.cacheChangingModulesFor / cacheDynamicVersionsFor. Filtering only narrows which repos are queried.
  • How does filtering interact with --refresh-dependencies?
    --refresh-dependencies bypasses caches and re-hits the network; with filtering, those network hits only go to the candidate repos, so even a refresh stays fast by avoiding dead-end lookups.

saying these in an interview costs you the question

  • Claiming filtering reduces how often snapshots are re-validated — that's cache TTL config, not filtering.
  • Saying it speeds up downloads of the artifacts themselves — it reduces metadata lookups, not transfer size.
  • Forgetting to escape the dot in the *ByRegex group patterns.

context