skip to content

What is maven-metadata.xml and what role does it play, especially for SNAPSHOT artifacts?

level: seniorimportance: should knowfreq 40%

answer

  1. index of available versions
  2. snapshot timestamp+buildNumber
  3. snapshotVersions mapping
  4. maven-metadata-<repoid>.xml
  5. updatePolicy / -U refresh

basics

~20 s

maven-metadata.xml is a small index file in a repository that lists the available versions of an artifact (and, for snapshots, the latest timestamped build). Maven reads it to figure out which concrete version to download.

solid answer

~40 s

`maven-metadata.xml` is repository metadata that complements the static artifact layout. At the `groupId/artifactId/` level it lists `<versions>`, the `latest`, and the `release` version. Inside a `version` directory for a SNAPSHOT it records the latest `<snapshot>` with its `timestamp` and `buildNumber`, plus a `<snapshotVersions>` mapping so Maven can resolve `1.0-SNAPSHOT` to the concrete uniquely-named file like `artifact-1.0-20240115.103045-7.jar`. Without it, Maven couldn't pick the newest deployed snapshot from a shared remote. Each version has its own `maven-metadata.xml` per repository, and copies exist both remotely and locally (e.g. `maven-metadata-central.xml`, `maven-metadata-local.xml`) so Maven can compare. The `<snapshots><updatePolicy>` governs how often Maven refetches this file. Corruption or staleness here is a classic cause of snapshot resolution bugs; `-U` forces a refresh.

code

xml · 17 lines
xml
<metadata>
  <groupId>com.acme</groupId>
  <artifactId>lib</artifactId>
  <version>1.0-SNAPSHOT</version>
  <versioning>
    <snapshot>
      <timestamp>20240115.103045</timestamp>
      <buildNumber>7</buildNumber>
    </snapshot>
    <snapshotVersions>
      <snapshotVersion>
        <extension>jar</extension>
        <value>1.0-20240115.103045-7</value>
      </snapshotVersion>
    </snapshotVersions>
  </versioning>
</metadata>

go deeper

for a junior

It's an index file listing available versions.

for a middle

Know it maps 1.0-SNAPSHOT to a concrete timestamped build.

for a senior

Use it to debug snapshot staleness, updatePolicy, and per-repo metadata copies.

for a principal

Reason about snapshot retention policies on the repository manager and metadata-corruption failure modes at scale.

## The problem it solves The repository layout (GAV -> path) is static: Maven can compute the path of a known release. But two things aren't knowable from a path alone: 1. **Which versions exist** for an artifact. 2. **For a SNAPSHOT, which exact build is newest** — because each deployed snapshot gets a unique timestamped filename. `maven-metadata.xml` is the index that answers these. ## Two flavours / locations - **Group/artifact level** (`groupId/artifactId/maven-metadata.xml`): lists `<versioning>` with `<latest>`, `<release>`, and `<versions>`. - **Version level for snapshots** (`groupId/artifactId/1.0-SNAPSHOT/maven-metadata.xml`): contains `<snapshot>` with `<timestamp>` and `<buildNumber>`, and `<snapshotVersions>` mapping classifier/extension to the concrete value. ## Snapshot resolution in practice When you depend on `com.acme:lib:1.0-SNAPSHOT`, a shared remote may hold many timestamped builds: `lib-1.0-20240115.090000-5.jar`, `...-6.jar`, etc. Maven reads the version-level `maven-metadata.xml` to learn the latest (`timestamp` + `buildNumber`) and downloads that specific file. The logical name stays `1.0-SNAPSHOT`. ```xml <metadata> <groupId>com.acme</groupId> <artifactId>lib</artifactId> <version>1.0-SNAPSHOT</version> <versioning> <snapshot> <timestamp>20240115.103045</timestamp> <buildNumber>7</buildNumber> </snapshot> <lastUpdated>20240115103045</lastUpdated> <snapshotVersions> <snapshotVersion> <extension>jar</extension> <value>1.0-20240115.103045-7</value> <updated>20240115103045</updated> </snapshotVersion> </snapshotVersions> </versioning> </metadata> ``` ## Local vs remote copies Maven keeps per-repository copies in the local cache, suffixed by repo id: `maven-metadata-central.xml`, `maven-metadata-local.xml`, etc. It compares these against the remote (subject to `updatePolicy`) to decide whether a newer snapshot exists. ## Refresh policy The `<repository><snapshots><updatePolicy>` value (`daily` default, or `always`/`never`/`interval:NN`) controls how often the metadata is refetched. `-U` forces a refresh now. Stale or corrupt metadata is a leading cause of "my build won't pick up the new snapshot" — deleting the cached metadata or using `-U` resolves it. ## Note on releases Releases are immutable, so version-level metadata is mainly relevant to snapshots; the group/artifact-level metadata still tracks the list of release versions (used by tools and range resolution).

  • Why do deployed snapshots have timestamped filenames instead of all being literally 1.0-SNAPSHOT.jar?
    So a shared remote can retain multiple builds without overwriting; maven-metadata.xml maps the logical 1.0-SNAPSHOT to the newest timestamped file via timestamp+buildNumber.
  • Where does Maven keep its view of remote metadata locally and why suffix it?
    In the local cache as maven-metadata-<repoId>.xml; the repo-id suffix lets Maven track metadata per source repository independently and compare them.

saying these in an interview costs you the question

  • Saying maven-metadata.xml stores the actual bytecode/classes.
  • Believing every snapshot deploy overwrites a single 1.0-SNAPSHOT.jar on the remote (timestamped uniqueness is the default).
  • Confusing version-level snapshot metadata with the group/artifact version-list metadata.

context