CommandLineRunner vs ApplicationRunner — Running Code at Startup
Fast recall
Quick revision
Core answer
String[] args; `ApplicationRunner` receives ApplicationArguments which parses --option=value pairs from non-option arguments. Use @Order to control execution sequence when multiple runners exist. If any runner throws an exception, application startup fails — ApplicationFailedEvent fires instead of ApplicationReadyEvent. For logic that should not block readiness, use an @EventListener(ApplicationReadyEvent.class) instead.Whether the candidate knows when runners execute in the lifecycle and the difference in argument handling
Using `@PostConstruct` for startup logic that depends on the full context being ready — `@PostConstruct` runs during bean initialization, not after all beans are created
Mention that runners execute after `ApplicationStartedEvent` but before `ApplicationReadyEvent`, explain `@Order` for controlling sequence, and contrast with `SmartLifecycle` and `@EventListener(ApplicationReadyEvent.class)`
Interview-ready guide
Interview answer
CommandLineRunner and ApplicationRunner are Spring Boot's hooks for startup logic that needs the full application context — database seeding, integration health checks, cache preloading, feature flag registration.
When they run
- All beans are created and injected
- The embedded web server is started
- Runners execute
ApplicationReadyEventfires — the application is now ready for traffic
`CommandLineRunner` vs `ApplicationRunner`
CommandLineRunner.run(String... args)receives the raw command-line arguments as a string arrayApplicationRunner.run(ApplicationArguments args)receives a typed object — callargs.getOptionValues("name")for--name=valueflags andargs.getNonOptionArgs()for positional arguments- For most startup tasks the type does not matter; prefer
ApplicationRunnerwhen you need to inspect specific command-line flags
Sequencing
@Order(1)on each runner class; lower values execute earlier- An exception in any runner propagates and fails the startup — wrap non-critical checks in try/catch
Alternatives
@EventListener(ApplicationReadyEvent.class)— runs after runners; failure doesn't block readiness; right for service registration@PostConstruct— too early; runs during bean init before the server startsSmartLifecycle— for components with explicit start/stop phase coordination
In an interview, the strong answer is: runners for blocking init that must complete before traffic, `ApplicationReadyEvent` for non-blocking post-startup tasks, `SmartLifecycle` for phased lifecycle coordination, never `@PostConstruct` for cross-bean initialization.
CommandLineRunner vs ApplicationRunner — Running Code at Startup
Direct Answer
Both interfaces run code after the ApplicationContext is fully initialized and the embedded server has bound its port. CommandLineRunner receives raw String[] args; ApplicationRunner receives ApplicationArguments which parses --option=value pairs from non-option arguments. Use @Order to control execution sequence when multiple runners exist. If any runner throws an exception, application startup fails — ApplicationFailedEvent fires instead of ApplicationReadyEvent. For logic that should not block readiness, use an @EventListener(ApplicationReadyEvent.class) instead.
Common Mistakes & Pitfalls
Using @PostConstruct for startup logic that depends on the full context being ready — @PostConstruct runs during bean initialization, not after all beans are created
Check your understanding
Answer these without looking back at the article.
- Why is `@PostConstruct` not appropriate for logic that depends on the full application context?
- What happens if a `CommandLineRunner` throws an exception?
- How would you choose between `ApplicationRunner` and an `@EventListener(ApplicationReadyEvent.class)`?
- How does `SmartLifecycle` differ from a runner, and when would you use it?
Related interview prep categories
1Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.