Back to Blog
spring-bootstartupperformancegraalvmjvmjava

Spring Boot Startup Time Optimization: From 8 Seconds to Under 2 (2026)

Slow Spring Boot startup hurts developer productivity and Kubernetes pod scheduling. Learn the key techniques to cut startup time - lazy initialization, GraalVM native, and class data sharing.

J

JOptimize Team

May 23, 2026· 8 min read

A Spring Boot app that takes 8 seconds to start is 8 seconds of blocked developer feedback, 8 seconds of Kubernetes readiness probe timeout, and 8 seconds of unavailability during rolling deploys. Startup time matters - and for most apps, it can be cut dramatically with targeted changes.


Measure Before You Optimize

Enable Spring Boot's startup actuator endpoint to see exactly which beans take the longest:

spring.jmx.enabled=false logging.level.org.springframework.boot.autoconfigure=DEBUG

Or use the startup endpoint:

management.endpoints.web.exposure.include=startup
curl http://localhost:8080/actuator/startup | jq '.timeline.events | sort_by(.duration) | reverse | .[0:10]'

This shows the 10 slowest beans during startup - always start here before guessing.


Technique 1: Lazy Initialization

By default, Spring initializes every bean at startup. Lazy initialization defers bean creation until first use:

# application.properties spring.main.lazy-initialization=true

Typical result: 40-60% startup time reduction. The trade-off is that the first request to each lazy bean takes slightly longer (one-time cost).

For specific beans that are known to be slow:

@Component @Lazy // Only initialized when first injected public class HeavyReportGenerator { // Complex initialization... }

Warning: Lazy init can hide startup errors. A misconfigured bean that would fail at startup now fails on first use. Run integration tests with lazy init disabled to catch these.


Technique 2: Exclude Unused Auto-Configurations

Spring Boot auto-configures hundreds of things. If you don't use them, exclude them:

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, // If no database SecurityAutoConfiguration.class, // If custom security FlywayAutoConfiguration.class, // If no migrations ThymeleafAutoConfiguration.class, // If pure REST API WebMvcAutoConfiguration.class // If using WebFlux }) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }

Or in properties:

spring.autoconfigure.exclude=\ org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\ org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration

Technique 3: JVM Class Data Sharing (AppCDS)

AppCDS creates a shared archive of loaded classes, so subsequent JVM startups skip class loading:

# Step 1: Generate the archive (run once after build) java -XX:ArchiveClassesAtExit=app.jsa -jar app.jar # Step 2: Use the archive on every startup java -XX:SharedArchiveFile=app.jsa -jar app.jar

Spring Boot 3.3+ supports CDS out of the box:

# Spring Boot 3.3+ - built-in CDS support mvn spring-boot:process-aot # AOT processing mvn spring-boot:build-image # Includes CDS by default

Typical result: 20-35% startup improvement with no code changes.


Technique 4: Spring AOT (Ahead-of-Time Processing)

Spring Boot 3.0+ supports AOT compilation, which moves runtime reflection work to build time:

<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>process-aot</goal> </goals> </execution> </executions> </plugin>
mvn spring-boot:process-aot package java -Dspring.aot.enabled=true -jar app.jar

AOT pre-computes bean definitions and proxy classes at build time. Startup improvement: 15-25%.


Technique 5: GraalVM Native Image (Maximum Reduction)

For microservices where startup time is critical (serverless, Kubernetes with frequent scaling), GraalVM native image compiles your Spring Boot app to a native binary:

<plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> </plugin>
mvn -Pnative native:compile ./target/myapp # Starts in ~50-200ms

Before/After comparison (real Spring Boot app):

ApproachStartup TimeMemory
Default JVM8.2s320MB
Lazy init3.1s310MB
Lazy + CDS2.2s295MB
AOT1.8s280MB
GraalVM Native0.12s55MB

GraalVM caveats: Reflection-heavy frameworks, dynamic proxies, and runtime class loading need explicit configuration. Spring Boot 3.x has good native support, but third-party libraries may need hints.


Quick Wins Checklist

# Add to application.properties for immediate improvement spring.main.lazy-initialization=true spring.jmx.enabled=false spring.mvc.pathmatch.use-suffix-pattern=false # Disable unused actuator endpoints management.endpoints.enabled-by-default=false management.endpoint.health.enabled=true

Common Mistakes to Avoid

  • Enabling lazy init in production without testing - lazy beans fail on first use instead of startup; always test with lazy init on
  • Not measuring before optimizing - use the startup actuator endpoint; the bottleneck is rarely what you expect
  • Going straight to GraalVM - try lazy init and CDS first; they're much easier and often sufficient
  • Heavy @PostConstruct methods - initialization logic in @PostConstruct runs synchronously during startup; defer it to ApplicationReadyEvent if it can wait

Summary

Most Spring Boot startup time problems are solved by: enabling lazy initialization (biggest impact, easiest change), excluding unused auto-configurations, and using AppCDS. Spring AOT adds further improvement with minimal effort. Reserve GraalVM native image for services where sub-200ms startup is a hard requirement - it's powerful but adds build complexity.


Detect Startup Performance Issues in Your Codebase

JOptimize identifies heavy @PostConstruct methods, eagerly-loaded beans that should be lazy, and auto-configuration anti-patterns that slow down your Spring Boot startup.

Cut your Spring Boot startup time - free scan, no configuration required.

Want to go deeper?

Master Spring Boot, security, and Java performance with hands-on courses.

Detect issues in your project

JOptimize finds N+1 queries, EAGER collections, and 70+ other issues in your Java codebase — in under 30 seconds.