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.


JOptimize detects this automatically

Scan your Java project in 30 seconds — free, no credit card.

Try free →

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.

Detect issues in your project

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