Slow and non-deterministic builds hurt CI and trust; Maven has specific remedies for both.
Maven builds are often slower than they need to be. Levers, roughly in order of payoff:
- Parallel reactor:
-T 1Cbuilds independent modules concurrently (one thread per core). Plugins must be marked thread-safe; Maven warns about the rest. - mvnd (the Maven Daemon): a long-running, warmed-up JVM with a native client that cuts startup from seconds to milliseconds and runs modules in parallel by default. Maven 4 integrates these ideas.
- maven-build-cache-extension: caches module outputs keyed by inputs (sources, POM, dependencies), locally or in a remote store, so unchanged modules are restored rather than rebuilt. Add it in
.mvn/extensions.xmland tunemaven-build-cache-config.xml. - Skip what you don't need:
-DskipTestsfor local packaging,-ooffline when the local repo is warm,-pl/-amfor a subset,-Dmaven.javadoc.skip. - Reduce plugin executions: enforcer, checkstyle and site generation can run in a separate CI job. Use
-Dmaven.test.redirectTestOutputToFile=trueand Surefire forking tuned for your machine. - Check what's slow with
-Dorg.slf4j.simpleLogger.showDateTime=trueor a profiler extension (maven-profiler).
Reproducible builds: with project.build.outputTimestamp set (<project.build.outputTimestamp>2026-01-01T00:00:00Z</project.build.outputTimestamp>, updated at release), the jar, source and javadoc plugins normalize file timestamps and ordering so the same inputs give byte-identical artifacts. Pin every plugin version, avoid version ranges and LATEST, and use the dependency lock approach of a BOM plus enforcer requireUpperBoundDeps/dependencyConvergence to keep resolution stable. artifact:compare (maven-artifact-plugin) verifies reproducibility against a reference build.
CI tips: cache ~/.m2/repository, use the wrapper, pass --batch-mode and --no-transfer-progress.
Example
# .mvn/maven.config (defaults applied to every mvn invocation in this repo)
--batch-mode
--no-transfer-progress
-T 1C
# .mvn/extensions.xml
# <extensions>
# <extension>
# <groupId>org.apache.maven.extensions</groupId>
# <artifactId>maven-build-cache-extension</artifactId>
# <version>1.2.0</version>
# </extension>
# </extensions>
# pom.xml property for reproducible archives
# <project.build.outputTimestamp>2026-01-01T00:00:00Z</project.build.outputTimestamp>
mvnd verify # Maven Daemon: warm JVM, parallel by default
mvn -o -pl api -am -DskipTests package # offline, subset of modules
mvn verify -Dmaven.build.cache.enabled=true # with the cache extension installed
mvn clean verify artifact:compare # check the build is reproducible
# CI: cache ~/.m2/repository between runs; always use ./mvnwRemember
- -T 1C and mvnd parallelize and remove JVM startup cost
- The build cache extension restores unchanged modules
- project.build.outputTimestamp plus pinned versions give byte-identical builds
- Cache ~/.m2 and use --batch-mode in CI
Watch out for
- Enabling -T with plugins that aren't thread-safe and getting intermittent build failures.