Spring Boot 4.0 shipped in November 2025 alongside Spring Framework 7. As of mid-2026, the current release line is 4.1, and the 3.x era is officially over: open-source support for Spring Boot 3.5 ended on June 30, 2026.

That last part changes the conversation. This isn’t “should we adopt the shiny new major version.” It’s “our current version no longer gets free security patches.”

This article covers what actually changed in Boot 4, what breaks in practice for a typical 3.5 application, and a straight answer on whether your team should upgrade now or wait.

One thing this article is not: a step-by-step migration walkthrough. We have a separate Spring Boot 3 to 4 Migration Guide for the mechanics. This is the decision piece.

What Shipped in Boot 4 and Framework 7

Spring Boot 4 is a coordinated major release across the portfolio: Spring Framework 7, Spring Security 7, and a Jakarta EE 11 baseline (Servlet 6.1, Persistence 3.2, Validation 3.1). Tomcat 11 and Jetty 12.1 are the embedded server versions.

The Java baseline stays at 17. That’s a deliberate choice: most 3.x applications can upgrade Boot without a JDK migration. Newer JDKs are fully supported, and if you’re upgrading anyway, landing on Java 21 or 25 is the sensible target.

Here’s the headline list, with an honest read on how much each one will affect an existing application:

ChangeWhat it isBlast radius for a typical 3.5 app
Jackson 3New default JSON library, new Maven coordinates and packagesHigh. Anything touching Jackson internals or third-party Jackson modules
HttpHeaders reworkNo longer implements MultiValueMap, map-style methods removedMedium. Compile errors wherever headers were treated as a map
Removed deprecated APIsEverything deprecated during 3.x is goneMedium. Depends on how many warnings you ignored
Modularized codebaseBoot split into smaller, focused jarsLow to medium. Bites if you depend on internals or write custom auto-configuration
JSpecify null safetyorg.jspecify annotations across the portfolioLow. Opt-in benefit, some new IDE and static analysis warnings
Built-in API versioningversion attribute on request mappingsNone. Pure addition
Jakarta EE 11 / Servlet 6.1Updated spec baselineLow. The painful namespace jump already happened in Boot 3

Jackson 3 is the big one

Boot 4 makes Jackson 3 the default. Jackson 3 moved to new Maven coordinates under tools.jackson and new package names to match, with one important exception: the annotations (@JsonProperty, @JsonIgnore, and friends) stay in com.fasterxml.jackson.annotation, so most entity and DTO code compiles untouched.

The pain shows up at the edges. Custom serializers, ObjectMapper configuration code, and third-party libraries that ship Jackson 2 modules all need attention. Boot 4 keeps Jackson 2 support in a deprecated form, with the old configuration properties moved to a spring.jackson2.* namespace, so there’s an escape hatch. But it’s a ramp, not a destination.

HttpHeaders stopped pretending to be a Map

Spring Framework 7 dropped the MultiValueMap contract from HttpHeaders. Headers are case-insensitive pairs, and the map abstraction never fit well. Practically, that means calls like headers.containsKey(...), headers.keySet(), and headers.entrySet() are gone, replaced by containsHeader(...), headerNames(), and headerSet(). There’s a deprecated asMultiValueMap() fallback to ease the transition.

It’s a mechanical fix, but it’s scattered. Interceptors, filters, test assertions, and client code all touch headers.

JSpecify null safety

The entire Spring portfolio migrated from Spring’s own @Nullable/@NonNull annotations to JSpecify, the industry-standard nullness annotations. Spring’s old JSR-305-flavored annotations are deprecated.

For your own code, this is opt-in and genuinely useful. Mark a package @NullMarked and everything is non-null by default, with @Nullable as the explicit exception:

import org.jspecify.annotations.Nullable;

// In package-info.java: @NullMarked
public interface CustomerRepository {

    // Returns null when no customer matches. The annotation makes
    // that contract visible to the compiler and static analysis,
    // not just to whoever reads the Javadoc.
    @Nullable Customer findByEmail(String email);
}

IntelliJ, NullAway, and Error Prone all understand JSpecify. Because Spring’s own APIs are now annotated, tooling can finally tell you when you’re dereferencing something Spring might legitimately return as null.

Built-in API versioning

Framework 7 added first-class API versioning. No more custom header resolvers or URL-parsing hacks. You declare the strategy once:

spring:
  mvc:
    apiversion:
      use:
        header: X-API-Version

Then map handlers to versions directly:

@GetMapping(path = "/orders/{id}", version = "1")
public OrderV1 getOrderV1(@PathVariable Long id) { ... }

@GetMapping(path = "/orders/{id}", version = "1.1+")
public Order getOrder(@PathVariable Long id) { ... }

Fixed versions match exactly. A baseline version like 1.1+ matches that version and everything above it until a newer handler takes over. If your team has ever maintained a homegrown versioning scheme, this alone is a quality-of-life upgrade.

Modularized starters

Boot’s codebase was restructured from a few large jars into many smaller, focused modules. Your existing starter declarations keep working, so most teams won’t notice at the dependency level. Where it bites: custom auto-configurations, anything importing from Boot’s internal packages, and build tooling that made assumptions about spring-boot-autoconfigure being one big artifact.

What Breaks in Practice

The release notes tell you what changed. Here’s what actually eats the time when you run the upgrade on a real 3.5 application, in rough order of hours lost:

The dependency ecosystem, not your code. Every third-party library that ships a Spring Boot starter needs a Boot-4-compatible release: API documentation tools, cloud SDKs, observability agents, that one internal shared library your platform team owns. Most major libraries shipped compatible versions within months of GA, and by mid-2026 the ecosystem is in decent shape. But “decent” isn’t “complete.” Your dependency tree is the real migration scope, and you won’t know until you audit it.

Jackson 3 fallout in the long tail. The apps that hurt are the ones with custom serializers, mix-ins, ObjectMapper beans configured in code, or third-party Jackson modules for things like money types or Kotlin. Serialization behavior differences also tend to surface at runtime, not compile time, which is why staging soak time matters more for this upgrade than usual.

The deprecation bill comes due. Everything Spring deprecated during the 3.x years is now removed. Teams that treated deprecation warnings as a to-do list have an easy time. Teams that suppressed them get the full invoice at once. A quick way to size this: build your current app with deprecation warnings on and count them.

Property and configuration drift. As with every major release, some configuration property namespaces moved. These don’t fail the compile. They fail quietly, at runtime, as defaults you didn’t intend.

If your 3.5 app is boring in the best sense, current dependencies, few deprecation warnings, no exotic Jackson usage, the upgrade is closer to a sprint task than a project. The blast radius scales with how much cleverness has accumulated in the codebase.

The Support-Window Math

This is the part that turns “eventually” into “this quarter.”

Spring’s open-source support policy gives each minor release roughly 13 months of free support. The dates that matter right now:

  • Spring Boot 3.5: OSS support ended June 30, 2026. Already past.
  • Spring Boot 4.0: OSS support ends December 31, 2026.
  • Spring Boot 4.1: OSS support runs to July 31, 2027.
Boot 3.5 OSS ended Jun 30, 2026 Boot 4.0 OSS ends Dec 31, 2026 Boot 4.1 OSS ends Jul 31, 2027 today May 2025 Jan 2026 Jan 2027 Jul 2027
Free support windows as of July 2026. The 3.5 window is already closed, and 4.0's closes within months, which is why 4.1 is the target.

Read that first line again. If you’re on 3.5 today, you’re not deciding whether to leave a supported version. You’ve already left it. The next CVE in Spring, Tomcat, or a managed dependency will get a patch in 4.x and, for free users, nothing in 3.5. Commercial support extends 3.x for years, and for some organizations that’s the right bridge. But it’s a purchasing decision, not a default.

The second implication is subtler: don’t target 4.0. Its OSS window closes at the end of 2026, months away. Teams that migrate to 4.0 now buy themselves a second, smaller upgrade almost immediately. Go straight to the current 4.1 line:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>4.1.0</version>
</parent>

The “always wait for the ecosystem to settle” instinct served teams well in the Boot 2-to-3 era, when the Jakarta namespace change made early upgrades genuinely painful. The math is different this time. The waiting period already happened: Boot 4 has been GA since November 2025, the ecosystem has had multiple quarters to catch up, and the version you’d be waiting on is the one that just lost support.

Upgrade Now or Wait: By Team Situation

Greenfield project: start on 4.1. No decision to make. Starting a new service on 3.5 in mid-2026 means starting on an unsupported version. You also get JSpecify null safety and API versioning from day one instead of retrofitting them.

Healthy 3.5 app with CI and a real test suite: schedule it now. Not because Boot 4 features demand it, but because the support window already closed. For an app with current dependencies and good tests, plan for days to a couple of weeks, with most of the effort in dependency reconciliation and staging verification. The migration guide covers the mechanics step by step.

3.5 app with a gnarly dependency tree or heavy Jackson customization: audit first, then schedule. Run the dependency audit described below before committing to a timeline. If a load-bearing library still lacks a Boot-4-compatible release, you have a concrete blocker to track instead of vague hesitation. Just be honest about what waiting means: every month on 3.5 is a month of unpatched exposure, unless you’re paying for commercial support.

Still on 2.x or early 3.x: do not leapfrog. Get to 3.5 first. The 2-to-3 jump carries the Java 17 baseline and the javax-to-jakarta namespace migration, and those need to land and stabilize before you layer Jackson 3 and the Framework 7 changes on top. Two sequenced migrations with a stable checkpoint between them beat one big bang where every failure is ambiguous. Start with the Spring Boot 2 to 3 Migration Guide, stabilize on 3.5, then take the 3 to 4 guide as a separate project. Yes, 3.5 is past OSS support, which makes the whole sequence more urgent, not skippable.

How to De-Risk the Upgrade

Three things do most of the risk reduction, whichever bucket you’re in.

Run a dependency audit before you touch the parent version. List every dependency that isn’t managed by the Boot BOM, and for each one, check whether a Boot-4-compatible release exists. Pay special attention to anything that registers Jackson modules or ships its own auto-configuration. This turns the upgrade from an unknown into a checklist, and it’s an afternoon of work.

Let OpenRewrite do the mechanical part. OpenRewrite ships recipes for the Boot 4 upgrade that handle version bumps, property migrations, and API replacements like the HttpHeaders method renames. Run the recipe, then review the diff like a pull request from a fast, literal-minded contributor. We covered the workflow in Simplify Spring Boot Version Migration with OpenRewrite.

Soak in staging longer than feels necessary. The Jackson 3 switch is exactly the kind of change that passes every unit test and then serializes a date differently in one API response. Run the upgraded build in staging against realistic traffic, diff representative API responses against the 3.5 output, and watch the logs for deprecation warnings and property-binding complaints before you promote.

When to Get Help

If your app is a standard Spring Boot service with current dependencies and decent test coverage, you can run this upgrade in-house with the migration guide and OpenRewrite doing the heavy lifting.

The cases that justify outside help look different: a portfolio of services that all need to move on a coordinated schedule, a dependency tree with abandoned libraries that need replacement rather than upgrading, heavy custom Jackson or auto-configuration code, or a team that’s still on 2.x and facing two sequenced migrations while also shipping features.

We do this work regularly. If your team is staring down a Boot 4 upgrade that’s bigger than a sprint, or you’re not sure which bucket you’re in, reach out and we can walk through your specific situation.

Frequently Asked Questions

Is Spring Boot 3.5 still supported?

Open-source support for Spring Boot 3.5 ended on June 30, 2026. There will be no more free security patches for any 3.x branch. Commercial support from Broadcom/Tanzu extends 3.5 for years, but without a paid subscription, staying on 3.5 means running unpatched.

What Java version does Spring Boot 4 require?

Java 17 is the minimum, same floor as Spring Boot 3, so most 3.x applications can upgrade without touching the JDK. Newer JDKs are fully supported, and if you’re doing the upgrade anyway, moving to Java 21 or 25 at the same time is worth considering for the runtime improvements.

What are the biggest breaking changes in Spring Boot 4?

Jackson 3 becomes the default JSON library, which changes Maven coordinates and package names for anything that touches Jackson internals. HttpHeaders no longer implements MultiValueMap, so map-style calls like keySet and containsKey are gone. APIs deprecated during the 3.x line have been removed, and the Boot codebase was split into smaller modules, which can break code that reached into internals.

Should I upgrade from Spring Boot 2.x directly to Spring Boot 4?

No. Get to Spring Boot 3.5 first, which forces the Java 17 and Jakarta namespace migrations, and stabilize there. Then make the 3.5 to 4 jump as a separate project. Combining both migrations into one big-bang upgrade makes every failure ambiguous and doubles your debugging surface.

Java Modernization Readiness Assessment

15 questions your team should answer before starting a migration. Takes 10 minutes. Could save you months.