Measuring and cutting startup time
Find the slow beans instead of guessing, then decide what is safe to defer.
Open this lesson in the learning hubKey points
- Startup cost is dominated by three things: classpath scanning, condition evaluation, and beans that do real work in their constructor or
@PostConstruct. - Measure before changing anything.
BufferingApplicationStartuprecords every step and the/actuator/startupendpoint reports them sorted by duration. - Eagerly connecting to a database, a broker or a remote configuration server during bean creation is usually the single largest item, and it is also what makes startup fail when a dependency is briefly unavailable.
spring.main.lazy-initialization=truedefers bean creation until first use. It genuinely speeds up local development, but it moves wiring errors from deployment to the first request - a poor trade in production.- A better targeted fix is
@Lazyon the specific expensive beans, keeping fail-fast behaviour for everything else. - For large applications, the
spring-context-indexergenerates a component index at build time so scanning reads one file instead of walking the classpath.
Example
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application.class);
// Record the startup timeline so /actuator/startup can report it.
// Bounded: it keeps the most recent N events rather than growing.
app.setApplicationStartup(new BufferingApplicationStartup(2048));
app.run(args);
}
}
/*
* curl localhost:8080/actuator/startup | jq '.timeline.events
* | sort_by(-.duration) | .[0:5]'
*
* A typical result - the answer is nearly always one bean, not "Spring is slow":
*
* spring.beans.instantiate entityManagerFactory 4.10s
* spring.beans.instantiate liquibase 1.80s
* spring.beans.instantiate kafkaAdminClient 0.90s
* spring.context.refresh 0.30s
* spring.beans.instantiate objectMapper 0.02s
*/
// Targeted, rather than making the whole application lazy:
@Component
@Lazy
class ReportGenerator {
ReportGenerator(TemplateEngine engine) {
engine.precompileAll(); // 3 seconds, and only needed by one endpoint
}
}
Measure with /actuator/startup first - it is almost always one eager bean doing I/O, not the framework.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Spring Boot course, and every lesson in it is listed on the Spring Boot contents page.