Ways to make maven build faster

In this blog post, I will explain how I reduced maven build time for the project at my workplace.
Project
I work on a multi module maven project and project has following structure.

Project is built on following tech stack
- Spring Boot
- Maven
- Junit
- PostgreSQL
- Rabbit MQ
- Docker
Maven Build
Typically we build our project with below command.
mvn clean package
Code language: Bash (bash)
Let’s record the time taken to build the project
Builds | 1 | 2 | 3 | 4 | 5 |
Time ( Min ) | 02:47 | 02:20 | 02:23 | 02:29 | 02:22 |
Avg. Time ( Min ) | 02:30 |
Maven supports multi thread building. So I ran following command and recorded the build times.
mvn clean package -T 2C
Code language: Bash (bash)
Builds | 1 | 2 | 3 | 4 | 5 |
Time ( Min ) | 02:18 | 02:17 | 02:19 | 02:24 | 02:25 |
Avg. Time ( Min ) | 02:18 |
There is slight decrease in build time but it is not significant.
[INFO] Reactor Summary:
[INFO] parent-project ..................................... SUCCESS [1.559 s]
[INFO] parent-project-client ..................................... SUCCESS [9.242 s]
[INFO] parent-project-common..................................... SUCCESS [9.097 s]
[INFO] parent-project-migration..................................... SUCCESS [1.009 s]
[INFO] parent-project-persistence..................................... SUCCESS [7.933 s]
[INFO] parent-project-war..................................... SUCCESS [02.03 min]
[INFO] parent-project-component-test................................... SUCCESS [4.054 s]
[INFO] parent-project-performance-test................................. SUCCESS [1.073 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
Code language: Bash (bash)
So I analyzed the my project to see which module is taking more time to build.
My project contains significant number of unit test cases so I ran the build by skipping unit test cases with below command.
mvn clean package -DskipTests
Code language: Bash (bash)
[INFO] Reactor Summary:
[INFO] parent-project ..................................... SUCCESS [1.314 s]
[INFO] parent-project-client ..................................... SUCCESS [8.990 s]
[INFO] parent-project-common..................................... SUCCESS [3.769 s]
[INFO] parent-project-migration..................................... SUCCESS [0.143 s]
[INFO] parent-project-persistence..................................... SUCCESS [4.527 s]
[INFO] parent-project-war..................................... SUCCESS [21.293 s]
[INFO] parent-project-component-test................................... SUCCESS [4.504 s]
[INFO] parent-project-performance-test................................. SUCCESS [1.083 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
Code language: Java (java)
Base on build times with unit tests and with out unit tests, we can conclude that unit tests were impacting the build time.
war project was taking more time to build as it had all the unit test cases.
Forking and Parallel Test execution
It is clear from the results that tests are major contributors in build time. So I was looking for ways to speedup the test case execution. Luckily maven-sure-fire
plugin supports forking and parallel test execution to speed up the build. we are using same plugin in our projects.
The plugin supports different configurations. You need to mix and match configuration options and values to achieve the optimum execution time. Please visit the documentation page to see all the configuration options available.
For my project following configuration gave the lowest execution time.
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.0</version>
<configuration>
<argLine>-Xmx2G -XX:MaxPermSize=1G -XX:-UseSplitVerifier -XX:-TieredCompilation -XX:TieredStopAtLevel=1</argLine>
<parallel>methods</parallel>
<forkCount>3C</forkCount>
<reuseForks>true</reuseForks>
<threadCount>20</threadCount>
</configuration>
</plugin>
Code language: XL (xl)
Note |
To use forking and parallel test execution feature following are minimum requirements. Junit 4.7+ Surefire plugin 2.16+ |
After this change I ran the maven build command again
mvn clean package
Code language: Bash (bash)
Clearly we can see that war project is building faster this time.
[INFO] Reactor Summary:
[INFO] parent-project ..................................... SUCCESS [1.947 s]
[INFO] parent-project-client ..................................... SUCCESS [8.431 s]
[INFO] parent-project-common..................................... SUCCESS [4.619 s]
[INFO] parent-project-migration..................................... SUCCESS [0.120 s]
[INFO] parent-project-persistence..................................... SUCCESS [7.892 s]
[INFO] parent-project-war..................................... SUCCESS [ 01.16 min]
[INFO] parent-project-component-test................................... SUCCESS [3.316 s]
[INFO] parent-project-performance-test................................. SUCCESS [0.773 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
Code language: Java (java)
Builds | 1 | 2 | 3 | 4 | 5 |
Time ( Min ) | 01:43 | 01:39 | 01:34 | 01:34 | 01:39 |
Avg. Time ( Min ) | 01:37 |
Since my project is multi module project, I tried to take advantage of Maven Daemon project and see whether it would fasten the build
Maven Daemon
Maven Daemon project aims at providing faster Maven builds using techniques known from Gradle and Takari.
Advantages
- The JVM for running the actual builds does not need to get started a new for each build.
- The class loaders holding classes of Maven plugins are cached over multiple builds. The plugin jars are thus read and parsed just once.
Limitations
- By default, mvn daemon is building your modules in parallel using multiple CPU cores. If your source tree does not support parallel builds, pass -T 1 on the command line to make your build serial.
- Can not be used in CI/CD pipeline
How to install Maven Daemon
On Windows
- Download the windows ZIP from https://github.com/mvndaemon/mvnd/releases
- Unzip to a directory of your choice
- Add the
bin
directory toPATH
in environment variables - Test whether
mvnd
works:

Please visit the link for installation instructions on Linux and Mac OS
Now lets run the builds with maven daemon.
mvnd clean package
Code language: Bash (bash)
Builds | 1 | 2 | 3 | 4 | 5 |
Time ( Min ) | 01:39 | 01:26 | 01:20 | 01:20 | 01:22 |
Avg. Time ( Min ) | 01:24 |
I tried using Maven Daemon with multi threading
mvnd clean package –T 2C
Code language: Bash (bash)
Builds | 1 | 2 | 3 | 4 | 5 |
Time ( Min ) | 01:15 | 01:20 | 01:18 | 01:21 | 01:22 |
Avg. Time ( Min ) | 01:19 |
mvnd clean package –T 4C
Code language: Bash (bash)
Builds | 1 | 2 | 3 | 4 | 5 |
Time ( Min ) | 01:20 | 01:21 | 01:21 | 01:22 | 01:20 |
Avg. Time ( Min ) | 01:21 |
I got optimum execution time with mvnd clean package –T 2C
command.
Comparing the build times
Build Command | Avg. Build Time | delta |
mvn clean package | 02:30 | NA |
mvn clean package -T 2C | 02:22 | – 5 % |
mvn clean package ( parallel unit tests) | 01:37 | – 35% |
mvnd clean package ( parallel unit tests) | 01:24 | – 44% |
mvnd clean package -T 2C ( parallel unit tests) | 01:19 | – 47% |
mvnd clean package -T 4C ( parallel unit tests) | 01:21 | – 46% |
I was able to reduce the build time of my project by 47%