The release of Spring Boot 4 marks an expected and deliberate break in the Java ecosystem. In the original transcript, the presenter sometimes says "Springwood," but the context is clear: this is indeed Spring Boot 4 and its major evolutions. This version builds on Spring Framework 7, revisits its internal structure, and offers a modern foundation for building applications and microservices. The ambition is to lighten dependencies, bring clarity to modularization, and enforce a healthier upgrade path.

The tone of the source content is that of a guided review: it goes from release notes to the migration guide, then to practical changes around dependencies, starters, and HTTP clients. The article below does not narrow the content but expands and explains it, with concrete examples, use cases, and a focus on the why and how. The goal is to give you an operational view to plan a migration, understand the impacts, and act without surprises.

Key takeaways from the sources

The two key documents cited are the release notes and the migration guide. The migration guide provides more details on breaking changes and replacements.

Context and vision of the release

Spring Boot 4 is presented as one of the biggest updates in recent years. Why such a scope? Because it repositions the project around strict modularization and a modern foundation (Spring Framework 7), which implies changes to dependencies, starters, and practices. This is not a minor version: it is a milestone that aims to avoid piling up technical debt and to better separate production and tests.

The transcript stresses a practical point: the version is already available in Spring Initializr. That means new projects can start directly with Spring Boot 4, without hacks. For a concrete use case, imagine a new microservices project: starting from a Boot 4 base lets you benefit from the latest conventions, rationalized dependencies, and a clearer build/test pipeline.

This kind of release requires a mindset shift. Why? Because you can no longer rely on deprecated APIs while waiting. The version removes many APIs deprecated in 3.x, which forces migration of existing applications. It is effort, but it is also a healthy cleanup that avoids ambiguous behavior and old-generation libraries that linger.

Warning

Spring Boot 4 removes APIs deprecated in 3.x. Any application that uses them will break at build time or runtime if migration is not anticipated.

Technical foundation: Spring Framework 7 and Java 17/25

One of the central axes is alignment with Spring Framework 7. Why is this important? Because Spring Boot is not just a set of starters: it depends on the Spring core for bean management, web, security, and observability. By moving to Framework 7, Boot 4 adopts a foundation that targets modernity and clearer upgrade paths.

On the JVM, the minimum version is Java 17, with support for Java 25. This creates a clear framework: no need to support legacy versions that complicate builds. The how is simple: your pipelines must compile and test on Java 17 at minimum. A typical use case is an organization that wants to standardize its application fleet: enforcing Java 17 simplifies tooling and enables modern performance and observability tools.

The choice of a Java 17 minimum also has a positive impact on teams. You can use newer language features, standardize compatible libs, and reduce incompatibilities. For microservice architectures, this means all services can share a coherent toolset, which simplifies maintenance and security audits.

Why Java 17 is a pivot

Java 17 is a solid LTS that brings optimizations, long-term stability, and broad compatibility with modern frameworks.

JavaScript
// Example Gradle configuration for Java 17
plugins {
    id "java"
    id "org.springframework.boot" version "4.0.0"
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

Modularization and new dependencies

Modularization is presented as one of the major changes. Until now, some starters included both runtime and test dependencies in a single block. Boot 4 further separates these layers, with distinct modules for runtime and for tests. Why? To lighten the production classpath, speed up startup, and limit version conflicts.

Concretely, this results in new artifacts or split artifacts. The AOP case is mentioned: the dependency is separated into a main module and a test module. The how? In `pom.xml` or `build.gradle`, you explicitly declare the modules you need. This allows teams to avoid accidentally shipping test tools to production.

This change also promotes better dependency readability. For teams that apply strict library governance, separating scopes becomes a lever: you can verify that only required dependencies are in production. For a regulated environment, this is a concrete gain: fewer possible CVEs and simpler audits.

JavaScript
// Maven example: runtime / test separation for AOP (illustration)
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop-test</artifactId>
    <scope>test</scope>
</dependency>

Direct effect on Docker images

Finer-grained dependencies reduce image size and build times, which is critical for fast CI/CD pipelines.

Migration from Spring Boot 3.5 to 4

The migration guide stresses a key step: first move to Spring Boot 3.5, then migrate to 4. Why this recommendation? Because 3.5 is the transition point where deprecations are clearly signaled. If you skip this step, you risk ignoring warnings and hitting blocking errors directly.

The how is very pragmatic: first, upgrade the application to 3.5, fix deprecated warnings, adjust code, then move to 4. This assumes a full build and test cycle. A concrete use case is an e-commerce monolith that uses older starters: cleaning up deprecated APIs in 3.5 lets you anticipate impacts and isolate changes before the final jump.

The removal of classes and methods deprecated in 3.x is deliberate. It pushes the adoption of more current patterns and avoids obsolete practices lingering. It is an initial investment, but it rationalizes the codebase. For teams, migration can be an opportunity to add missing integration tests, to validate each change.

Warning

If your code depends on classes deprecated in 3.x, a direct migration to 4 will break. Going through 3.5 is essential to identify and fix these usages.

JavaScript
// Example: configure a migration profile via properties
spring.profiles.active=migration
spring.main.banner-mode=off
logging.level.org.springframework=INFO

New features and ecosystem

Among the cited new features is support for Gradle 9, while keeping compatibility with Gradle 8.x. The why is clear: allow teams to gradually migrate their build pipelines. The how? By adjusting the Gradle wrapper, then checking compatibility of Spring Boot plugins and internal plugins.

Another important point is the addition of auto-configuration and configuration properties for HTTP service clients. This makes it easier to create declarative and consistent clients. In a microservices architecture, this allows centralizing parameters like timeouts, retries, or tracing headers, instead of duplicating them in each client.

The version also addresses API versioning via properties. Why? To enable clear governance of endpoints, separating versions while keeping code maintainable. The how? By configuring prefixes or routing conventions in the application configuration, then organizing controllers explicitly. This pattern makes it easier to evolve API contracts without breaking existing clients.

JavaScript
// Example of API versioning via configuration
api.versioning.enabled=true
api.versioning.prefix=/api
api.versioning.default-version=v1

Microservices use case

A microservice can expose v1 and v2 simultaneously, keeping legacy clients while introducing new routes.

Starters, replacements, and concrete cases

The guide mentions deprecated starters and their replacements. The why is twofold: clarify starter responsibilities and align their naming with the new modules. For teams, this means a migration may involve changes in build dependencies, but also in code imports.

The transcript notably highlights the change around the AOP starter and the separation of test modules. You can generalize this to other libraries: the logic is to make explicit what is runtime and what is test. This reshuffles some historical `pom.xml` files, but offers better control.

A concrete case cited by the author is the creation of a new microservices project that relies on Spring Boot 4. In this scenario, you immediately benefit from modularization and recent configurations. For example, an order service can adopt an auto-configured HTTP client, normalized timeouts, and API versioning consistent with other domain services.

JavaScript
// Example of auto-configured HTTP client (pseudo-illustration)
http.clients.orders.base-url=https://orders.internal
http.clients.orders.connect-timeout=2000
http.clients.orders.read-timeout=5000

Warning

Updating starters may involve artifact name changes. Check the official documentation to avoid resolution errors.

JavaScript
// Example of organizing versioned routes (illustration)
GET /api/v1/customers
GET /api/v2/customers
POST /api/v1/orders
POST /api/v2/orders

Finally, the transcript mentions an interesting detail: a small issue in the documentation (a Spring Session class incorrectly referenced). This reminds us that Spring Boot is open source and that you can contribute by opening issues. This point is practical: if you find an inconsistency in the guide, report it, which will improve overall quality for the entire community.

Contribute: why and how

Opening an issue with a clear example helps the Spring team and benefits all users, especially during migration periods.

Spring Boot Spring Framework 7 Java 17 Migration Gradle 9 Microservices API versioning