Before you read any changelog, you need to understand what Spring Boot 4 actually is, where it came from, and what problem it’s trying to solve in 2026.
Welcome to Spring/SpringBoot Essentials 2026, a series for Java engineers who want to understand the Spring ecosystem deeply, not just use it.
This article is the entry point to the series. Not a changelog. Not a migration guide. A map.
Before you can make sense of what changed in Spring Boot 4, you need to understand what Spring Boot is actually doing under the hood, why the version number jumped from 3 to 4, and what the people who built it are trying to solve for. The rest of the series builds on top of that context.
Next up: in Spring Boot Essentials 2026: Everything That Changed from Spring 6 to Spring 7, we cover BeanRegistrar, JSpecify null safety, native API versioning, modularization, and the full dependency purge. Read here.
Start Here: Spring Boot vs. Spring Framework
Most developers use Spring Boot without ever clearly separating it from Spring Framework in their mental model. The distinction matters.
Spring Framework is the core, the dependency injection container, the bean lifecycle, the AOP infrastructure, the transaction management, the web layer (MVC and WebFlux), the data access abstractions. It’s been around since 2003. It’s the engine.
Spring Boot is the configuration layer on top. It adds:
- Auto-configuration: the logic that looks at your classpath and automatically wires up beans so you don’t have to
- Starters: curated, tested dependency bundles (spring-boot-starter-web pulls in Tomcat, Jackson, Spring MVC, correctly versioned together)
- An opinionated default stance: sensible defaults for everything, override only what you need
- Production tooling: health checks, metrics, externalized configuration, graceful shutdown
The version relationship is direct:

When you see “Spring Boot 4,” you’re looking at a distribution of Spring Framework 7. Every architectural decision in Framework 7 is surfaced through Boot 4.
This is why major Boot versions are significant. They’re not just configuration changes, they’re a new version of the engine.
Why Spring Boot 4 Exists
To understand Boot 4, you need to understand what Boot 3 did and what problem it left unsolved.
Boot 3 Was a Forced Modernization
Spring Boot 3 (released late 2022) was uncomfortable on purpose.
It broke things that had worked fine for years:
- It set Java 17 as the minimum baseline, forcing teams off Java 8 and 11
- It completed the javax → jakarta namespace migration, which broke every library that hadn’t been updated to Jakarta EE 9
- It introduced GraalVM Native Image support, compile your Spring app to a native binary, start in milliseconds, use a fraction of the memory
Boot 3’s job wasn’t to add exciting features. It was to tear out the old foundation and pour a new one. The javax → jakarta migration alone required rebuilding the import structure of the entire Java EE ecosystem. That was the work.
Boot 3 paid the migration tax. Boot 4 spends the dividend.
Boot 4 Is What That Investment Was For
Spring Boot 4 (released late 2025) is built on Spring Framework 7 and Jakarta EE 11. It assumes the new foundation is in place and builds on top of it.
The pattern repeats: Boot 3 prepared the platform. Boot 4 uses it.
The specific things Boot 4 is designed to deliver, leaner startup, smaller binaries, cloud-native performance, first-class observability, were architecturally impossible in the Boot 2 era. The jakarta migration, the Java 17 baseline, the AOT infrastructure from Boot 3 were prerequisites.
Understanding this sequence changes how you think about Boot 4. It’s not a random collection of new features. It’s the payoff of a multi-year strategic direction.
What Spring Boot 4 Actually Changes
There are four areas where Boot 4 makes a meaningful structural difference. These are not changelog items, they’re shifts in how the framework operates.
1. Startup Is No Longer Reflection-Driven
The most fundamental change in Boot 4 is invisible in your code. It’s in how Spring builds your application context.
In Boot 3, startup looked like this:
- Spring scans your classpath
- Reads @Configuration classes through reflection
- Evaluates @Conditional expressions at runtime to decide which beans to create
- Resolves dependencies and builds the full application context
All of this happens at runtime, every time your application starts. For a medium-sized Spring Boot application, this process alone can take 3-8 seconds.
Boot 4 introduces a new API which is BeanRegistrar: that changes when this work happens:
// Boot 3 — reflection-based, evaluated at runtime
@Configuration
public class PaymentConfig {
@Bean
@ConditionalOnProperty("payment.stripe.enabled")
public StripeGateway stripeGateway(StripeProperties props) {
return new StripeGateway(props.getApiKey());
}
}
// Boot 4 — explicit, evaluated at build time
public class PaymentRegistrar implements BeanRegistrar {
@Override
public void register(BeanRegistry registry, Environment env) {
if (env.getProperty("payment.stripe.enabled", Boolean.class, false)) {
registry.registerBean("stripeGateway", StripeGateway.class,
spec -> spec.supplier(ctx ->
new StripeGateway(ctx.getBean(StripeProperties.class).getApiKey())
)
);
}
}
}
The difference: the @Bean / @Configuration approach requires Spring to interrogate your bytecode at runtime. The BeanRegistrar approach is explicit, Spring doesn’t need to infer anything. The AOT compiler can process it at build time.
For a containerized microservice, this is the difference between a 5-second cold start and a sub-second one. In a Kubernetes environment where pods are scaled and replaced continuously, that gap compounds.
You don’t have to migrate to BeanRegistrar immediately, Boot 4 still supports @Configuration. But new code and new projects should prefer the explicit approach.
2. The Dependency Footprint Got Smaller
Boot 3 had a monolithic auto-configuration jar: spring-boot-autoconfigure. It contained the auto-configuration logic for databases, message queues, web servers, caches, observability, all of it, in one artifact. Even if your application only needed database auto-configuration, you dragged in the entire jar.
Boot 4 splits this into over 70 focused modules:
spring-boot-autoconfigure-jdbc
spring-boot-autoconfigure-kafka
spring-boot-autoconfigure-redis
spring-boot-autoconfigure-web-servlet
spring-boot-autoconfigure-actuator
... (70+ total)
You only get the auto-configuration for what you actually declare as a dependency.
This matters for two reasons:
GraalVM native compilation. The AOT compiler has to process every @ConditionalOnClass it can find. With a smaller classpath, it does less work, produces smaller binaries, and produces them faster.
Startup classpath scanning. Less code on the classpath means Spring has less to evaluate at startup, even in JVM mode, not just native.
For most developers, this change is completely transparent. Your spring-boot-starter-web dependency still works the same way. What changes is what’s pulled in transitively, and how lean the resulting artifact is.
3. Resilience Is Now Built In
Microservices fail. Not sometimes, routinely. External APIs return 503. Database connections time out. Message brokers restart.
Boot 3 had no native answer to this. You reached for Resilience4j, Spring Cloud Circuit Breaker, or Bucket4j. Three different libraries, three different configuration models, three different health indicator integrations.
Boot 4 brings two resilience primitives directly into the core framework:
// Automatic retry with exponential backoff — no Resilience4j needed
@Service
public class InventoryService {
@Retryable(maxAttempts = 3, backoff = @Backoff(delay = 200, multiplier = 2.0))
public InventoryStatus checkStock(String productId) {
return warehouseClient.getStock(productId); // external HTTP call
}
@Recover
public InventoryStatus fallback(Exception ex, String productId) {
log.warn("Warehouse unavailable for {}, returning cached status", productId);
return inventoryCache.getLast(productId);
}
}
// Concurrency limiting — prevent a slow endpoint from overwhelming your thread budget
@Service
public class ReportService {
@ConcurrencyLimit(value = 5) // max 5 concurrent report generations
public Report generateAnnualReport(String tenantId) {
// CPU-intensive, long-running work
return reportEngine.buildAnnual(tenantId);
}
}
Both annotations are AOP-based, Spring wraps the method call. Crucially, they preserve the calling thread’s security context, trace context, and Scoped Values. This was the persistent problem with external resilience libraries: their retry threads didn’t carry the caller’s context, breaking distributed tracing and security propagation.
The built-in implementation doesn’t have this problem because it never leaves Spring’s context machinery.
4. Observability Got Native
Observability in Boot 3 was a configuration exercise. Micrometer was the abstraction layer. Tracing required wiring up a Brave or OpenTelemetry bridge. Getting trace IDs to propagate correctly through @Async methods, RestTemplate calls, and reactive chains was a non-trivial integration task.
Boot 4 changes the default:
# application.yml — Boot 3 (manual OTel setup required)
management:
tracing:
sampling:
probability: 1.0
zipkin:
tracing:
endpoint: http://zipkin:9411/api/v2/spans
# Also needed: manual OTel SDK configuration, tracer bean setup, exporter config...
# application.yml — Boot 4 (native OTLP out of the box)
management:
otlp:
tracing:
endpoint: http://otel-collector:4318/v1/traces
metrics:
export:
url: http://otel-collector:4318/v1/metrics
What Boot 4 Requires From You
Boot 4 isn’t free. It raises the floor.
Java 21 is the new minimum. Java 17 runs it technically, but you won’t get Virtual Threads (first-class in Boot 4), Scoped Values, or Project Leyden startup optimizations without Java 21+. In practice, Java 21 is the real baseline. Java 25 is the recommended production target in 2026.
Jakarta EE 11. The javax → jakarta migration that Boot 3 introduced is table stakes now. If your third-party libraries haven’t made that transition, they don’t work with Boot 4. This is the most common hidden breakage in the ecosystem.
Undertow is gone. It doesn’t support Servlet 6.1, which is required by Jakarta EE 11. If you’re using Undertow as your embedded server, you need to switch to Tomcat 11+ or Jetty 12.1+ before upgrading.
Jackson 3. Boot 4 ships Jackson 3, which changes package names (com.fasterxml.jackson.* → tools.jackson.*) and the exception hierarchy. Custom serializers and ObjectMapper beans need updating.
JUnit 4 is removed. The junit-vintage-engine bridge is gone. JUnit 4 tests won’t run — not with an error, just silently. Migration to JUnit 5 (Jupiter) is required.
None of these are arbitrary. Each removal is explained by a technical constraint: Undertow couldn’t support Jakarta EE 11, Jackson 2 had reached API design limits, JUnit 4 had been superseded for years. The Spring team isn’t making changes for the sake of it.
The Technology Stack in 2026
Here’s the complete picture of what Boot 4 runs on:

This is not a list of updates. It’s a coherent platform, every layer aligned to the same Java version, the same Jakarta namespace, the same observability standard.
Should You Start With Boot 4 or Boot 3?
Starting a new project in 2026: Start with Boot 4. There’s no technical reason to start on Boot 3 today. The platform is stable, the ecosystem has caught up, and you’ll be building on the right foundation from day one.
Running a Boot 3 application: You don’t need to migrate immediately. Boot 3 is still maintained. Migrate when you have a concrete reason, a major feature needing Virtual Threads, a performance goal that requires the leaner startup, or a migration cycle already underway.
Running a Boot 2 application: This is where urgency applies. Boot 2’s Spring Framework 5.x baseline is no longer receiving security patches. The path is Boot 2 → Boot 3.5.x (clearing all deprecations) → Boot 4. Don’t skip the middle step.
The migration guide (Article 3 in this series) covers every breaking change and the exact code to fix each one.
The Direction of Travel
There’s a thread connecting everything in Boot 4, startup time, binary size, native compilation, cloud-native performance.
Spring Boot was born in an era of monolithic deployments. An application started once and ran for weeks. Startup time of 30 seconds was acceptable. Memory usage in the gigabytes was fine.
The deployment model changed. Kubernetes schedules and reschedules pods constantly. Serverless functions start on demand. Edge deployments run on constrained hardware. In these environments, a slow-starting, memory-heavy JVM application is a real operational problem.
Boot 3 laid the groundwork: Jakarta EE namespace, Java 17 baseline, GraalVM AOT infrastructure.
Boot 4 delivers on it: sub-second startup potential through BeanRegistrar and AOT repositories, lean dependency graph through modularization, minimal-reflection context construction.
The Spring team is not building for the enterprise server rooms of 2015. They’re building for a deployment model where applications start in milliseconds, scale down to zero, and run efficiently in containers on the edge.
If you understand that, every decision in Boot 4 makes sense.
Beyond the Code: The Realities of Engineering
Knowing what Spring Boot 4 is gives you technical depth. Making the case to your team for a major framework upgrade, framing the risk, getting alignment, owning the outcome, requires a completely different skill set.
I’ve distilled the unwritten rules of navigating decisions like these inside software companies into a practical field guide.
👉 Get “Beyond the Offer Letter” on Gumroad here: and learn how software companies actually work so you can accelerate your engineering career.
Spring Boot 4: The Big Picture was originally published in Javarevisited on Medium, where people are continuing the conversation by highlighting and responding to this story.
This post first appeared on Read More