What's New in Spring Boot 4.0

Spring Boot 4.0 (November 2025) is a major release built on Spring Framework 7 and Java 17+. It’s the most significant Spring release since Boot 3’s Jakarta EE migration. This article covers every change that affects a practicing developer.

Minimum Requirements

Spring Boot 3.xSpring Boot 4.0
Java1717 (baseline), 21 recommended
Spring Framework6.x7.x
Jakarta EE1011
Tomcat10.x11.x
Hibernate6.x7.x
Gradle (if used)7.x8.x

Spring Boot 4 requires Java 17 minimum. But Java 21 is the recommended runtime for new projects:

  • Virtual threads are stable (Java 21) and on by default in Spring Boot 4
  • Sequenced collections (SequencedCollection, SequencedMap) are available
  • Pattern matching for switch is final
  • Record patterns are final
  • Spring Framework 7 uses Java 21 APIs internally where available

If you’re on Java 17: upgrade works, but you miss virtual threads.

Virtual Threads On by Default

In Spring Boot 3.2+, you had to opt in:

# Boot 3.2 — opt in
spring:
  threads:
    virtual:
      enabled: true

In Spring Boot 4.0, virtual threads are on by default for Tomcat and @Async. No configuration needed. If you need to opt out (e.g., pinning issues with heavily synchronized code):

spring:
  threads:
    virtual:
      enabled: false

JSpecify Null Safety

Spring Framework 7 adopts JSpecify for null safety annotations — the first standardized, tooling-supported null safety for Java APIs.

// Spring Framework 7 APIs are annotated
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
import org.jspecify.annotations.NullMarked;

@NullMarked   // all APIs in this package are non-null by default
public class OrderService {

    public Order findById(UUID id) {  // return type is @NonNull
        return orderRepository.findById(id).orElseThrow();
    }

    public @Nullable Order findByIdOrNull(UUID id) {  // explicit nullable
        return orderRepository.findById(id).orElse(null);
    }
}

In your own code: annotate packages with @NullMarked and methods that return null with @Nullable. IntelliJ IDEA and the Kotlin compiler understand JSpecify — you get null safety warnings at compile time.

Jakarta EE 11

Spring Boot 4 moves from Jakarta EE 10 to Jakarta EE 11:

APIOldNew
Servlet6.06.1
JPA3.13.2
Bean Validation3.03.1
CDI4.04.1
JSON-B3.03.0

JPA 3.2 is the biggest change. Highlights:

  • find() with TypedQueryReference — compile-safe named queries
  • CriteriaBuilder.union() — finally, JPQL unions
  • Table schema generation improvements
  • @Id on records (experimental)
// JPA 3.2: @Id on records (Spring Boot 4 + Hibernate 7)
@Entity
public record OrderItem(
    @Id UUID id,
    UUID orderId,
    UUID productId,
    int quantity,
    BigDecimal price
) {}

Spring Framework 7 Key Changes

Declarative HTTP Clients (GA)

// Was experimental in Spring 6.1 — GA in Spring 7
@HttpExchange("http://inventory-service/api")
public interface InventoryClient {

    @GetExchange("/inventory/{productId}")
    Inventory getInventory(@PathVariable UUID productId);

    @PostExchange("/reservations")
    Reservation reserve(@RequestBody ReservationRequest request);
}

@Bean
InventoryClient inventoryClient(RestClient.Builder builder) {
    RestClient restClient = builder.baseUrl("http://inventory-service").build();
    RestClientAdapter adapter = RestClientAdapter.create(restClient);
    HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();
    return factory.createClient(InventoryClient.class);
}

This is Spring’s native declarative HTTP client — similar to Feign but part of the framework with no additional dependency.

RestClient (Stable Improvements)

// Exchange functions and streaming
restClient.get()
    .uri("/api/orders/stream")
    .retrieve()
    .toEntityFlux(OrderEvent.class)    // streaming response
    .subscribe(event -> processEvent(event));

Improved AOT (Build-Time) Processing

Spring Framework 7 extends AOT to more scenarios:

  • Conditional bean registration is pre-computed at build time
  • @Profile conditions resolved at build time for native images
  • Better @Conditional support without reflection hints

Removed: WebMVC.fn with HandlerFunctions

Spring Framework 7 removes the experimental functional web layer from Spring MVC. Use @RestController or the WebFlux functional API instead.

Hibernate 7 Changes

spring:
  jpa:
    properties:
      hibernate:
        # New in Hibernate 7: SQL logging via dedicated logger (not root)
        show_sql: false   # use logging.level instead
        format_sql: true
        # Hibernate 7 generates better SQL for complex joins
        query:
          plan_cache_max_size: 2048

Hibernate 7 improvements:

  • Better pagination SQL (fewer subqueries)
  • @SoftDelete annotation — soft deletion without custom logic
  • Better support for java.time types directly in @Column
  • Embeddable aggregate (JSON column mapping) improvements
// @SoftDelete — Hibernate 7
@Entity
@SoftDelete   // adds deleted/deleted_at column, filters all queries automatically
public class Order {
    @Id private UUID id;
    private OrderStatus status;
    // delete() now sets deleted=true, not DELETE FROM orders
}

Spring Security 7

// Deprecated in Security 6, removed in Security 7:

// ❌ Removed
http.antMatcher("/api/**")      // use requestMatchers()
http.mvcMatchers("/api/**")     // use requestMatchers()
http.authorizeRequests()        // use authorizeHttpRequests()
http.csrf().disable()           // use csrf(AbstractHttpConfigurer::disable)

// ✓ Current API
http.requestMatchers("/api/**")
    .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
    .csrf(AbstractHttpConfigurer::disable);

PassKeys (WebAuthn) support is GA in Spring Security 7 — passwordless authentication with hardware keys.

Actuator Changes

# New in Boot 4
management:
  endpoint:
    health:
      roles: ACTUATOR_ADMIN   # role required for full health details
  endpoints:
    web:
      exposure:
        include: health,info,prometheus
  # New: structured output format
  info:
    os:
      enabled: true
    process:
      enabled: true

/actuator/info now includes OS and process information by default — useful for debugging pod-level issues in Kubernetes.

Removed Deprecated APIs

Spring Boot 4 removes APIs deprecated in Boot 3.x:

// ❌ Removed in Boot 4
@SpringBootApplication.exclude()           // use @EnableAutoConfiguration(exclude=...)
SpringApplication.setBannerMode(Mode.OFF)  // use spring.main.banner-mode=off
TestRestTemplate.withBasicAuth()           // use getForEntity with HttpHeaders

// Spring MVC:
ModelAndView(String viewName, ModelMap model)  // use Map<String, Object> variant

// Security:
WebSecurityConfigurerAdapter   // use SecurityFilterChain beans (removed in Boot 3 too)

Check for deprecation warnings on Boot 3.x before migrating — everything deprecated in 3.x is gone in 4.x.

Dependency Upgrades

<!-- Spring Boot 4 manages these versions automatically -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>4.0.0</version>
</parent>

<!-- Key managed dependencies -->
<!-- Spring Framework: 7.0.x -->
<!-- Hibernate: 7.0.x -->
<!-- Micrometer: 1.14.x -->
<!-- Resilience4j: 2.3.x -->
<!-- Testcontainers: 1.20.x -->
<!-- Jackson: 2.18.x -->
<!-- Logback: 1.5.x -->
<!-- Netty: 4.2.x -->

What You’ve Learned

  • Spring Boot 4 requires Java 17 minimum; Java 21 is recommended for virtual threads
  • Virtual threads are on by default — no configuration needed
  • JSpecify null safety annotations are adopted across Spring Framework 7 APIs
  • Jakarta EE 11 brings JPA 3.2 with CriteriaBuilder.union() and @SoftDelete in Hibernate 7
  • Declarative HTTP clients (@HttpExchange) are GA — Spring’s native Feign alternative
  • Spring Security 7 removes deprecated antMatcher, authorizeRequests, and adds WebAuthn
  • All APIs deprecated in Boot 3.x are removed — fix deprecation warnings before migrating

Next: Article 56 — Migrating from Spring Boot 3.x to 4.0 — step-by-step migration guide.