Spring Boot
Spring Boot is how enterprises ship Java services in 2026 — not a replacement for Spring Core, but an opinionated layer that auto-wires datasources, Jackson, Tomcat, and Microme…
Introduction
Spring Boot is how enterprises ship Java services in 2026 — not a replacement for Spring Core, but an opinionated layer that auto-wires datasources, Jackson, Tomcat, and Micrometer from classpath + properties. A @SpringBootApplication class and a spring-boot-starter-web dependency give you a production HTTP server in minutes; the same stack without Boot requires hundreds of lines of XML or Java config.
This lesson covers auto-configuration (how @Conditional beans activate from classpath), starter dependencies (curated BOMs that pull compatible versions), Spring Boot Actuator (health, metrics, readiness for Kubernetes), and profiles (dev/staging/prod configuration without code forks).
Staff engineers treat Boot as infrastructure-as-code: understand condition evaluation, override defaults safely, and expose the right actuator endpoints — not blindly add starters until the fat JAR exceeds 200 MB.
Business problem
Spring Boot misuse creates operational debt:
- Fat JAR bloat: Adding
spring-boot-starter-*without understanding transitive deps — 300 MB images, slow K8s pulls. - Magic failures: Auto-config silently skipped — "works on my laptop" because local H2 on classpath, prod PostgreSQL missing driver bean.
- Actuator exposure:
/actuator/envpublic on internet — credentials leaked in incident report. - Profile drift:
application-prod.ymlmissing new property — staging passes, prod defaults to insecure value. - Startup regressions: Spring Boot 3.x upgrade breaks javax → jakarta — no condition report review before deploy.
Why this topic exists
Spring Boot solves the "getting to production" gap:
- Convention over configuration: Sensible defaults for embedded Tomcat, Jackson, Logback, HikariCP.
- Dependency management:
spring-boot-dependenciesBOM aligns Spring, Hibernate, Netty versions — no dependency hell. - Executable JAR:
java -jar app.jar— container-friendly deploy without external app server. - Observability built-in: Actuator + Micrometer — health probes, Prometheus scrape, startup timeline.
- Environment parity: Profiles + externalized config — same artifact, different
application-{profile}.yml.
Core concepts
Four Spring Boot pillars:
- Auto-configuration:
@AutoConfigurationclasses register beans when@ConditionalOnClass,@ConditionalOnMissingBean,@ConditionalOnPropertymatch — e.g. DataSource when JDBC on classpath. - Starters:
spring-boot-starter-web,starter-data-jpa,starter-actuator— thin POMs aggregating dependencies + auto-config. - Actuator: Production endpoints —
/health,/metrics,/info,/env— secured and exposed selectively. - Profiles:
spring.profiles.active=prodloadsapplication-prod.yml;@Profile("prod")on beans. - Externalized config: Properties hierarchy — command line > env vars > application.yml > defaults.
Internal architecture
Spring Boot startup and auto-config evaluation:
SpringApplication.run(App.class)│▼Load application.yml + application-{profile}.yml│▼@SpringBootApplication= @Configuration + @EnableAutoConfiguration + @ComponentScan│▼AutoConfigurationImportSelectorreads META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports│▼For each @AutoConfiguration class:@ConditionalOnClass? @ConditionalOnProperty? @ConditionalOnMissingBean?│├── MATCH → register beans (DataSource, JpaVendor, etc.)└── NO MATCH → skip (logged in DEBUG)Actuator (management.endpoints):/actuator/health → liveness/readiness (K8s probes)/actuator/metrics → Micrometer registry/actuator/prometheus → scrape endpoint
Auto-configuration, starters, actuator, and profiles:
Code walkthrough
Spring Boot application — auto-config, profiles, actuator:
- @SpringBootApplication: Enables auto-config scan — DataSource appears when JDBC + Hikari on classpath.
- ddl-auto: validate: Flyway/Liquibase owns schema — Hibernate never mutates prod tables.
- health probes: K8s uses /actuator/health/liveness and /readiness.
- @ConfigurationProperties: Type-safe binding vs scattered @Value injections.
// build.gradle.ktsplugins { id("org.springframework.boot") version "3.4.0" }dependencies {implementation("org.springframework.boot:spring-boot-starter-web")implementation("org.springframework.boot:spring-boot-starter-data-jpa")implementation("org.springframework.boot:spring-boot-starter-actuator")runtimeOnly("org.postgresql:postgresql")}@SpringBootApplicationpublic class PaymentApplication {public static void main(String[] args) {SpringApplication.run(PaymentApplication.class, args);}}// application.ymlspring:application:name: payment-servicedatasource:url: ${DB_URL:jdbc:postgresql://localhost:5432/payments}hikari:maximum-pool-size: 20jpa:hibernate:ddl-auto: validateprofiles:active: ${SPRING_PROFILES_ACTIVE:dev}management:endpoints:web:exposure:include: health,metrics,prometheus,infoendpoint:health:probes:enabled: truemetrics:tags:application: ${spring.application.name}// application-prod.yml — overrides only prod-specificspring:jpa:show-sql: falselogging:level:root: WARN// Custom auto-config override@Configurationpublic class DataSourceConfig {@Bean@ConfigurationProperties("spring.datasource.hikari")public HikariDataSource dataSource(DataSourceProperties props) {return props.initializeDataSourceBuilder().type(HikariDataSource.class).build();}}
Production example
Production Spring Boot deploy — K8s + Actuator + profiles:
- Non-root container: USER 1000 — security baseline for regulated workloads.
- Secrets via env: Never commit prod credentials — K8s Secret → SPRING_APPLICATION_JSON or env.
- Probe separation: Readiness checks DB; liveness only JVM up — avoid restart loops on DB blip.
- Actuator security: Public health only — lock /env and /heapdump.
# DockerfileFROM eclipse-temurin:21-jre-alpineCOPY build/libs/payment-service.jar /app.jarUSER 1000ENTRYPOINT ["java", "-XX:+UseZGC", "-jar", "/app.jar"]# kubernetes deployment snippetenv:- name: SPRING_PROFILES_ACTIVEvalue: prod- name: DB_URLvalueFrom:secretKeyRef: { name: db-credentials, key: url }livenessProbe:httpGet: { path: /actuator/health/liveness, port: 8080 }initialDelaySeconds: 30readinessProbe:httpGet: { path: /actuator/health/readiness, port: 8080 }# Secure actuator — Spring Security@BeanSecurityFilterChain actuatorSecurity(HttpSecurity http) {return http.securityMatcher("/actuator/**").authorizeHttpRequests(a -> a.requestMatchers("/actuator/health/**").permitAll().anyRequest().hasRole("OPS")).build();}
Enterprise case study
Streaming platform — Actuator leak and startup failure: A media company exposed all actuator endpoints on public ALB during a "quick debug." Attackers scraped /actuator/env containing AWS keys. Parallel incident: Spring Boot 3 migration — auto-config for Redis skipped because wrong starter (spring-data-redis without boot starter) — cache silently disabled, DB overload. Fixes: Spring Security actuator matcher, explicit spring-boot-starter-data-redis, and CI gate running with debug profile to print negative auto-config matches.
- Actuator: Expose health/prometheus only; IP allowlist for admin endpoints.
- Auto-config: Document required starters per module in archetype template.
- Upgrade: Use Boot 3 migration guide — jakarta.* imports, spring-security 6.
Performance considerations
Spring Boot performance:
- Cold start: Lazy initialization (
spring.main.lazy-initialization=true) trades first-request latency for faster startup — use cautiously. - Classpath scanning: Narrow
@SpringBootApplication(scanBasePackages)— faster startup in monoliths. - DevTools: Never in production — classloader restart overhead and security risk.
- Actuator overhead: Micrometer cardinality explosion — limit custom tag dimensions.
- Native image: GraalVM AOT for serverless — longer build, faster cold start.
Security considerations
Spring Boot security checklist:
- Actuator lockdown: Default Boot 3 exposes limited endpoints — verify
management.endpoints.web.exposure. - Actuator on separate port:
management.server.port=9090— network policy isolation. - Dependency scanning: OWASP dependency-check in CI — Boot BOM still pulls transitive CVEs.
- spring.config.import: Vault/AWS Secrets Manager — no secrets in git-tracked yml.
Scalability considerations
Scaling Boot services:
- Stateless pods: No local session state — scale HPA on CPU or custom metric from Actuator.
- Graceful shutdown:
server.shutdown=graceful— drain in-flight requests before K8s SIGTERM. - Config refresh: Spring Cloud Config optional — env vars + K8s ConfigMaps simpler for many teams.
- Virtual threads:
spring.threads.virtual.enabled=true(Boot 3.2+) — I/O scale without WebFlux.
Production challenges
Common Spring Boot production issues:
- Port already in use: Multiple apps default 8080 — set
server.portor K8s service mapping. - DataSource pool exhausted: Hikari defaults too small for virtual threads — tune max pool vs thread count.
- Missing @EnableScheduling/@EnableAsync: Annotations present but feature inactive — starter doesn't enable all.
- Logback config not picked up:
logback-spring.xmlnotlogback.xmlfor profile sections.
Common mistakes
- Adding starters without checking transitive deps — use `gradle dependencies` or `mvn dependency:tree`.
- Relying on spring.jpa.hibernate.ddl-auto=update in prod — use Flyway/Liquibase.
- Exposing /actuator/env and /actuator/beans publicly.
- Hardcoding profile-specific logic in Java instead of configuration files.
- Ignoring auto-config report after Boot version upgrade.
Debugging guide
Debug Spring Boot:
- Auto-config report: Run with
--debugor enableConditionEvaluationReportLoggingListener. - Actuator conditions:
/actuator/conditionsshows why beans skipped. - Failed to configure DataSource: Usually missing url/driver — check profile-specific yml.
- Startup timeline:
/actuator/startupor Flight Recorder — find slow bean init.
java -jar app.jar --debug 2>&1 | grep -A2 "Negative matches"curl -s localhost:8080/actuator/conditions | jq '.contexts.application.conditions'# Which profile active?curl localhost:8080/actuator/env/spring.profiles.active
Best practices
- Use Spring Boot BOM — avoid overriding managed versions unless CVE requires it.
- Externalize all environment-specific values — profiles + env vars + secrets manager.
- Enable health probe groups for Kubernetes — separate liveness from readiness checks.
- Pin Boot plugin version in build file — reproducible builds across team.
- Run OWASP dependency check in CI — starters don't eliminate CVE monitoring.
- Use `spring-boot-starter-test` with Testcontainers for integration parity.
Anti-patterns
- Copy-pasting entire application.yml from tutorial — understand each property.
- Multiple main classes without clear module boundaries.
- Disabling all auto-config (
@EnableAutoConfiguration(exclude=...)) without documenting why. - Using DevTools and spring.jpa.show-sql=true in production images.
- Custom parent POM that fights Boot dependency management.
Staff engineer notes
- Read the auto-config negative match report once per upgrade — it is the fastest Boot debug tool.
- Starters are contracts — if you need Redis, use the Boot starter, not raw spring-data-redis alone.
- Actuator is your production API — design exposure with same rigor as REST endpoints.
- Profiles are not environments — they are configuration slices; same code, different properties.
- Graceful shutdown + K8s terminationGracePeriodSeconds — prevent payment TX lost mid-flight.
Interview questions
Interview preparation
15 questions grouped by difficulty — expand any card for a model answer and follow-up probe.
Beginner
1What is Spring Boot auto-configuration?
BeginnerModel answer
Mechanism that automatically registers beans based on classpath, existing beans, and property values.
@AutoConfiguration classes use @ConditionalOn* annotations.
Example: spring-boot-starter-jdbc triggers DataSourceAutoConfiguration when DataSource class and JDBC driver present.
Reduces boilerplate vs manual @Configuration.
Follow-up probe
How disable one auto-config?
2What are Spring Boot starters?
BeginnerModel answer
- Convenience dependency descriptors
- e.g. spring-boot-starter-web pulls spring-webmvc, tomcat-embed, jackson, validation. Starters bundle compatible versions via spring-boot-dependencies BOM. You add one starter instead of listing 10 coordinates.
Follow-up probe
Create custom starter?
3What is Spring Boot Actuator?
BeginnerModel answer
- Production-ready features module
- health checks, metrics (Micrometer), env info, thread dump, heap dump. Endpoints under /actuator/*. Expose selectively via management.endpoints.web.exposure.include. K8s uses health/liveness and health/readiness probe groups.
Follow-up probe
Secure actuator?
4Explain Spring profiles.
BeginnerModel answer
- Logical environment labels
- spring.profiles.active=prod loads application-prod.yml and activates @Profile('prod') beans. Allows same JAR across dev/staging/prod with different config. Multiple profiles comma-separated. Default profile if none set.
Follow-up probe
Profile vs property?
5Difference @SpringBootApplication and @Configuration?
BeginnerModel answer
@SpringBootApplication = @Configuration + @EnableAutoConfiguration + @ComponentScan (defaults to package of main class).
Entry point for Boot apps.
@Configuration alone defines @Bean methods without enabling auto-config or scan unless added explicitly.
Follow-up probe
scanBasePackages?
Intermediate
6How override auto-configured bean?
IntermediateModel answer
- Define your own @Bean of same type
- @ConditionalOnMissingBean on auto-config skips default. Or exclude auto-config class via @EnableAutoConfiguration(exclude=DataSourceAutoConfiguration.class). Or override properties: spring.datasource.hikari.maximum-pool-size.
Follow-up probe
@Primary vs override?
7Property resolution order in Spring Boot?
IntermediateModel answer
- Command line args highest, then SPRING_APPLICATION_JSON env, OS env vars, application-{profile}.yml, application.yml, @PropertySource, defaults in @ConfigurationProperties. Later sources in same tier don't override earlier
- specific profile file overrides base application.yml.
Follow-up probe
@ConfigurationProperties vs @Value?
8Configure Kubernetes liveness vs readiness?
IntermediateModel answer
- management.endpoint.health.probes.enabled=true exposes /actuator/health/liveness (JVM alive, no deadlock) and /readiness (can accept traffic
- DB up). Liveness failure restarts pod; readiness failure removes from service endpoints. Don't put slow DB check on liveness.
Follow-up probe
Custom HealthIndicator?
9What is spring-boot-starter-parent / BOM?
IntermediateModel answer
- Dependency management POM
- pins versions for Spring ecosystem libraries. Gradle: io.spring.dependency-management plugin imports spring-boot-dependencies BOM. Ensures compatible Hibernate, Jackson, Netty versions without manual alignment.
Follow-up probe
Upgrade Boot safely?
10Why ddl-auto=validate in production?
IntermediateModel answer
- Hibernate checks schema matches entities but never ALTERs tables. Schema migrations owned by Flyway/Liquibase
- auditable, repeatable, reviewable. update/create-drop risk data loss and untracked DDL in prod.
Follow-up probe
Flyway vs Liquibase?
Advanced
11Design multi-tenant config with profiles.
AdvancedModel answer
Option A: one profile per tenant (doesn't scale).
Option B: single prod profile, tenant config in DB/Config Server.
import for tenant-specific property files.
Prefer external config service for 100+ tenants; profiles for environment (dev/staging/prod) only.
Follow-up probe
Spring Cloud Config?
12Debug 'DataSource bean not found' at startup.
AdvancedModel answer
Check: JDBC driver on classpath?
url set for active profile?
Excluded DataSourceAutoConfiguration?
Using wrong starter (jdbc vs jpa)?
Run --debug for negative matches.
Test with @DataJpaTest to isolate.
Follow-up probe
Multiple datasources?
13Compare Spring Boot 2 vs 3 migration impacts.
AdvancedModel answer
* namespace.
Spring Security 6 lambda DSL.
Minimum Java 17.
PathPatternParser default.
Removed deprecated classes.
Actuator endpoint changes.
Review dependency tree, run migration tool, update imports, test security config.
Follow-up probe
Spring Boot 3 + Java 21?
14Optimize Spring Boot cold start for serverless.
AdvancedModel answer
Lazy init (careful), AOT/native-image with GraalVM, reduce classpath scanning, exclude unused auto-config, smaller starters (exclude tomcat if using lambda web adapter), tiered compilation.
Measure with /actuator/startup or JFR.
Follow-up probe
Native image trade-offs?
15Architect observability for 50 Boot microservices.
AdvancedModel answer
Standardize: micrometer-registry-prometheus, actuator exposure, consistent metric tags (application, env).
OpenTelemetry agent for traces.
Structured JSON logging with traceId.
Platform team provides base starter-parent with security + actuator defaults.
Alert on health DOWN and error rate SLO.
Follow-up probe
Micrometer vs Dropwizard?
Hands-on exercise
Lab: Spring Boot essentials
- Create Boot app with starter-web + actuator — verify /actuator/health.
- Add application-dev.yml and application-prod.yml — toggle logging level via profile.
- Run with --debug — list which auto-configurations matched.
- Add custom HealthIndicator for external dependency — wire to readiness probe.
- Configure management.endpoints — expose only health and prometheus.
JavaSpring Boot: Auto Configuration, Starter Dependencies, Actuator, Profiles
Press Run to execute. Real javac + JVM via remote API. Falls back to simulator on network failure.Architecture trade-offs
- Auto-config vs explicit config: Auto-config speeds dev; explicit when you need full control or audit.
- Monolith vs microservices: Boot supports both — microservices add network ops cost.
- Embedded Tomcat vs external: Embedded standard for K8s; external Tomcat legacy enterprise.
- Properties vs YAML: YAML readable for nested config; properties simpler for K8s env mapping.
Summary
Spring Boot turns Spring Core into a production-ready platform — auto-configuration, starters, Actuator, and profiles are the operational toolkit every Java engineer uses daily. Understand condition evaluation and configuration hierarchy to debug startup failures and deploy safely to Kubernetes. Next: REST API design with controllers, DTOs, validation, and OpenAPI.
Key takeaways
- Spring Boot auto-configures beans from classpath + properties — read condition report when debugging.
- Starters bundle tested dependencies — use Boot starters, not raw Spring modules alone.
- Actuator powers K8s probes and metrics — expose minimally and secure admin endpoints.
- Profiles externalize environment config — same JAR, different application-{profile}.yml.
- Production: validate schema, graceful shutdown, lock down actuator, scan dependencies for CVEs.