eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

Course – Summer Sale 2026 – NPI EA (cat= Baeldung)
announcement - icon

Yes, we're now running our only Summer Sale. All Courses are 30% off until 20th July, 2026:

>> EXPLORE ACCESS NOW

Course – Summer Sale 2026 – NPI (cat=Baeldung)
announcement - icon

Yes, we're now running our only Summer Sale. All Courses are 30% off until 20th July, 2026:

>> EXPLORE ACCESS NOW

1. Introduction

In this tutorial, we’ll cover different configurations and setups that can help decrease Spring Boot startup time. First, we’ll go over Spring specific configurations. Second, we’ll cover Java virtual machine options. Finally, we’ll cover how we can leverage GraalVM and native image compilation to reduce startup time further.

2. Spring Tweaks

Before we start, let’s set up a test application. We’ll use Spring Boot version 2.5.4 with Spring Web, Spring Actuator, and Spring Security as dependencies. In pom.xml, we’ll add spring-boot-maven-plugin with configuration to pack our application in a jar file:

<plugin> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-maven-plugin</artifactId> 
    <version>${spring-boot.version}</version> 
    <configuration> 
        <finalName>springStartupApp</finalName> 
        <mainClass>com.baeldung.springStart.SpringStartApplication</mainClass> 
    </configuration> 
    <executions> 
        <execution> 
            <goals> 
                <goal>repackage</goal> 
            </goals> 
        </execution> 
    </executions> 
</plugin>

We run our jar file with the standard java -jar command and monitor the start time of our application:

c.b.springStart.SpringStartApplication   : Started SpringStartApplication in 3.403 seconds (JVM running for 3.961)

As we can see, our application starts at approximately 3.4 seconds. We’ll use this time as a reference for future tweaks.

2.1. Lazy Initialization

Spring Framework has support for lazy initialization. Lazy initialization means that Spring won’t create all beans on startup. Also, Spring will inject no dependencies until that bean is needed. Since Spring Boot version 2.2. it’s possible to enable lazy initialization using the application.properties:

spring.main.lazy-initialization=true

After building a new jar file and starting it as in the previous example, the new startup time is slightly better:

 c.b.springStart.SpringStartApplication   : Started SpringStartApplication in 2.95 seconds (JVM running for 3.497)

Depending on the size of our codebase, lazy initialization can result in a significant amount of startup time reduction. The reduction depends on the dependency graph of our application.

Also, lazy initialization has benefits during development while using DevTools hot restart functionality. An increased number of restarts with lazy initialization will enable JVM to optimize the code better.

However, lazy initialization has a few drawbacks. The most significant disadvantage is that the application will serve the first request slower. Because Spring needs time to initialize the required beans, another disadvantage is that we can miss some errors on startup. This can result in ClassNotFoundException during runtime.

2.2. Excluding Unnecessary Autoconfiguration

Spring Boot always favored convention over configuration. Spring may initialize beans that our application doesn’t require. We can check all autoconfigured beans using startup logs. Setting the logging level to DEBUG on org.springframework.boot.autoconfigure in the application.properties:

logging.level.org.springframework.boot.autoconfigure=DEBUG

In the logs, we’ll see new lines dedicated to autoconfiguration, starting with:

============================
CONDITIONS EVALUATION REPORT
============================

Using this report, we can exclude parts of the application’s configuration. To exclude part of the configuration, we use @EnableAutoConfiguration annotation:

@EnableAutoConfiguration(exclude = {JacksonAutoConfiguration.class, JvmMetricsAutoConfiguration.class, 
  LogbackMetricsAutoConfiguration.class, MetricsAutoConfiguration.class})

If we excluded the Jackson JSON library and some of the metrics configuration that we don’t use, we could save some time on startup:

c.b.springStart.SpringStartApplication   : Started SpringStartApplication in 3.183 seconds (JVM running for 3.732)

2.3. Other Minor Tweaks

Spring Boot comes with an embedded servlet container. By default, we get Tomcat. While Tomcat is good enough in most cases, other servlet containers can be more performant. In tests, Undertow from JBoss performs better than Tomcat or Jetty. It requires less memory and has a better average response time. To switch to Undertow, we need to change pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-undertow</artifactId>
</dependency>

The following minor improvement can be in the classpath scan. Spring classpath scanning is fast action. We can improve startup time by creating a static index when we have a large codebase. We need to add a dependency to the spring-context-indexer to generate the index. Spring doesn’t require any additional configuration. During compile-time, Spring will create an additional file in META-INF\spring.components. Spring will use it automatically during startup:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-indexer</artifactId>
    <version>${spring.version}</version>
    <optional>true</optional>
</dependency>

Since we have only one Spring component, this tweak didn’t produce significant results in our tests.

It’s worth noting the spring-context-indexer has been deprecated since Spring 6.1. More information about it can be found here.

Next, there are several valid places for application.properties (or .yml) files. Most usual are at classpath root or in the same folder as the jar file. We can avoid searching multiple locations by setting an explicit path with spring.config.location parameter and save a couple of milliseconds on searching:

java -jar .\target\springStartupApp.jar --spring.config.location=classpath:/application.properties

Finally, Spring Boot offers some MBeans to monitor our application using JMX. Turn off JMX entirely and avoid the cost of creating those beans:

spring.jmx.enabled=false

3. JVM Tweaks

3.1. Verify Flag

This flag sets bytecode verifier mode. Bytecode verification provides whether classes are properly formated and within JVM specification constraints. We set this flag on JVM during startup.

There are a couple of options for this flag:

  • -Xverify is the default value and enables verification on all non-bootloader classes. 
  • -Xverify:all enables verification of all classes. This setup will have a significant negative performance impact on startups.
  • -Xverify:none (or -Xnoverify). This option disables the verifier completely and will reduce startup time significantly.

We can pass this flag on startup:

java -jar -noverify .\target\springStartupApp.jar 

We’ll get a warning from JVM that this option is deprecated. Also, startup time will decrease:

 c.b.springStart.SpringStartApplication   : Started SpringStartApplication in 3.193 seconds (JVM running for 3.686)

This flag brings in a significant tradeoff. Our application can break during runtime with an error that we could catch earlier. This is one of the reasons this option is marked as deprecated in Java 13. Hence it will be removed in future releases.

3.2. TieredCompilation Flag

Java 7 introduced tiered compilation. The HotSpot compiler will use different levels of compilation for the code.

As we know, Java code first gets interpreted to bytecode. Next, bytecode gets compiled into machine code. This translation happens on the method level. C1 compiler compiles a method after a certain amount of calls. After even more runs C2 compiler compiles it increasing performance even more.

Using the -XX:-TieredCompilation flag, we can disable intermediate compilation tiers. This means that our methods will get interpreted or compiled with the C2 compiler for maximum optimization. This won’t result in a decrease in startup speed. What we need is to disable the C2 compilation. We can do this with -XX:TieredStopAtLevel=1 option. In conjunction with -noverify flag, this can reduce startup time. Unfortunately, this will slow down the JIT compiler at later stages.

TieredCompilation flag alone brings in solid improvement:

 c.b.springStart.SpringStartApplication   : Started SpringStartApplication in 2.754 seconds (JVM running for 3.172)

For an extra kick, running both flags from this section in conjunction reduces startup time even more:

 java -jar -XX:TieredStopAtLevel=1 -noverify .\target\springStartupApp.jar
c.b.springStart.SpringStartApplication : Started SpringStartApplication in 2.537 seconds (JVM running for 2.912)

4. Spring Native

Native image is Java code compiled using an ahead-of-time compiler and packed into an executable file. It doesn’t require Java to run. The resulting program is faster and less memory-dependent since there is no JVM overhead. The GraalVM project introduced native images and required build tools.

Spring Native is an experimental module that supports the native compilation of Spring applications using the GraalVM native-image compiler. The ahead-of-time compiler executes several tasks during build time that reduce startup time (static analysis, removal of unused code, creating fixed classpath, etc.). There are still some limitations to native images:

  • It doesn’t support all Java features
  • Reflection requires a special configuration
  • Lazy class loading is unavailable
  • Windows compatibility is an issue.

To compile an application to a native image, we need to add the spring-aot and spring-aot-maven-plugin dependency to pom.xml. Maven will create the native image on the package command in the target folder.

5. Conclusion

In this article, we explored different ways to improve the startup time of Spring Boot applications. First, we covered various Spring related features that can help reduce startup time. Next, we showed JVM-specific options. Last, we introduced Spring Native and native image creation.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

Course – Summer Sale 2026 – NPI EA (cat= Baeldung)
announcement - icon

Yes, we're now running our only Summer Sale. All Courses are 30% off until 20th July, 2026:

>> EXPLORE ACCESS NOW

Course – Summer Sale 2026 – NPI (All)
announcement - icon

Yes, we're now running our only Summer Sale. All Courses are 30% off until 20th July, 2026:

>> EXPLORE ACCESS NOW

eBook Jackson – NPI EA – 3 (cat = Jackson)