skip to content

Reproducible Builds

Making artifacts byte-for-byte stable by pinning the output timestamp and normalizing archive entries and ordering. A modern supply-chain question: can you prove this jar was built from that source?

on this pageshow

explore

questions

5

What is a reproducible build in Maven, and why would a team want byte-for-byte stable artifacts?

level: middleimportance: must knowfreq 55%

answer

  1. byte-for-byte identical
  2. same source -> same hash
  3. JAR is a ZIP: timestamps + order
  4. supply-chain verifiability
  5. outputTimestamp property

basics

~10 s

A reproducible build produces the exact same bytes in the output JAR/WAR every time you build the same source, regardless of when or where you build. It improves verifiability, caching, and supply-chain trust.

solid answer

~40 s

A reproducible (or deterministic) build means rebuilding identical source produces a byte-for-byte identical artifact, independent of build time, machine, or user. By default Maven JARs are NOT reproducible because the archive embeds the current timestamp on every entry and may order entries by filesystem order. Maven supports reproducibility primarily through the `project.build.outputTimestamp` property, which makes plugins like maven-jar-plugin and maven-archiver strip/normalize timestamps and sort entries deterministically. Benefits: independent parties can rebuild and verify a published artifact matches (supply-chain integrity, Reproducible Builds project), build caches and Docker layer caches stay stable, and diffs between releases reflect only real changes. It is a key control against tampering between source and binary.

code

xml · 3 lines
xml
<properties>
  <project.build.outputTimestamp>2024-01-01T00:00:00Z</project.build.outputTimestamp>
</properties>

go deeper

for a junior

Knows the phrase 'same source produces the same artifact bytes' and that it helps verify nothing was tampered with.

for a middle

Knows a JAR is a ZIP and the two main culprits (timestamps, ordering) and that one property addresses them.

for a senior

Can articulate supply-chain and caching trade-offs and pick a timestamp source (commit date vs fixed) for the org.

for a principal

Drives a verifiable-build policy across repos, integrates check-buildplan/compare into CI, and weighs reproducibility against tooling that injects nondeterminism.

## What 'reproducible' means A **reproducible build** is one where compiling the *same source code* with the *same toolchain* yields an **identical output file — byte for byte**, no matter **when**, **where**, or **by whom** it is built. If two people build commit `abc123` and the resulting `myapp-1.0.jar` files have the same SHA-256 hash, the build is reproducible. ## Why Maven artifacts are NOT reproducible by default A JAR/WAR is a ZIP archive. Two sources of non-determinism creep in: - **Timestamps:** every ZIP entry stores a last-modified time. By default Maven writes the *current wall-clock time*, so building at 10:00 vs 10:01 gives different bytes. - **Entry ordering:** files can be added in filesystem-dependent order, which varies between OSes and runs. There are smaller sources too (e.g. absolute paths, locale, or the JDK version baked into the manifest's `Build-Jdk`). ## Why teams want it - **Supply-chain trust / verifiability:** anyone can rebuild from source and confirm the published binary was not tampered with. This is the goal of the Reproducible Builds movement. - **Stable caching:** unchanged inputs produce unchanged outputs, so build caches (Maven build cache, Docker image layers) get cache hits. - **Clean diffs:** binary comparisons between releases reflect only real source changes. ## How you turn it on (the headline) Set a single property — the build timestamp Maven uses for archive entries: ```xml <properties> <project.build.outputTimestamp>2024-01-01T00:00:00Z</project.build.outputTimestamp> </properties> ``` The value can be an ISO-8601 instant or a Unix epoch seconds integer. Maven Archiver and the packaging plugins read it and normalize timestamps + ordering. Many teams set it to the commit date (e.g. via `git log`). Recent Maven parent POMs even let you set it to a literal `1` to derive it from the SCM commit in CI. ## Verifying Use `mvn artifact:check-buildplan` (the `maven-artifact-plugin`) to assert the build plan is reproducibility-friendly, and `mvn clean verify artifact:compare` against a reference deploy to confirm the bytes match.

  • Name two reasons a default Maven JAR is not reproducible.
    Each ZIP entry embeds the current build timestamp, and entries may be ordered by filesystem order which varies across machines/OSes.
  • How do you verify reproducibility?
    Run mvn artifact:check-buildplan to check the plan, then rebuild and compare hashes (e.g. artifact:compare against a reference) — identical SHA-256 means reproducible.

Like a recipe so precise that two cooks in different kitchens produce dishes you can't tell apart — even down to the plating.

saying these in an interview costs you the question

  • Saying reproducible just means the build 'always succeeds' or is deterministic in behavior — it specifically means identical output bytes.
  • Claiming Maven JARs are reproducible out of the box.

context

open as a page

How does project.build.outputTimestamp make a Maven archive reproducible, and what values can it take?

level: seniorimportance: must knowfreq 45%

basics

~10 s

Setting project.build.outputTimestamp gives Maven Archiver a fixed timestamp to stamp on every archive entry instead of the current time, and it sorts entries. It accepts an ISO-8601 instant or Unix epoch seconds.

open as a page

You inherit an existing Spring Boot Maven project that is not reproducible. Walk through the minimal steps to make and verify it reproducible.

level: middleimportance: should knowfreq 28%

basics

~10 s

Add project.build.outputTimestamp to the POM (often derived from the commit), make sure packaging plugin versions are current, then run mvn artifact:check-buildplan and rebuild twice to confirm the JAR hashes match.

open as a page

What does mvn artifact:check-buildplan do, and how does it fit into verifying a reproducible build?

level: seniorimportance: should knowfreq 30%

basics

~10 s

artifact:check-buildplan (from the maven-artifact-plugin) inspects your effective build plan and warns or fails if plugins are configured in a way that breaks reproducibility — for example if project.build.outputTimestamp is missing.

open as a page

Beyond the build timestamp, what other sources of non-determinism can break a reproducible Maven build, and how do you address them?

level: principalimportance: should knowfreq 22%

basics

~20 s

Besides timestamps, watch out for entry ordering, the JDK version baked into the manifest, locale/timezone effects, absolute paths, SNAPSHOT dependencies, and code generators that embed times. Pin the toolchain, avoid SNAPSHOTs, and normalize generated content.

open as a page