Spring Boot 3.x Features: Complete Guide to Major Updates (2022-2025)

What's New in Spring Boot 3.x? Understanding the Major Features

Spring Boot has long been the de facto standard for building production ready Spring applications with minimal configuration. The 3.x series, which began in November 2022, represents one of the most significant evolutionary leaps in the framework's history. This generation didn't just iterate on existing features; it fundamentally reimagined what a modern Java application framework should be.

From embracing Java 17's modern language features to pioneering support for GraalVM native images and virtual threads, Spring Boot 3.x has consistently pushed the boundaries of what's possible in the Java ecosystem. As we approach the release of Spring Boot 4.0 in November 2025, with 3.5 marking the final minor release in the 3.x line, it's the perfect time to reflect on the transformative features that have defined this generation.

This guide highlights the most impactful features from each release in the 3.x series, exploring how these features have solved real-world problems and transformed the way we build, deploy, and operate Spring applications. While we won't cover every single enhancement and bug fix, we'll focus on the game-changing capabilities that have shaped modern Spring development. For a complete list of all features and changes, you can visit the official Spring Boot documentation and release notes.

Quick Navigation: Spring Boot 3.x Releases

Spring Boot 3.0 (November 2022): The Foundation for Modern Java

Spring Boot 3.0 arrived as a watershed moment, making bold decisions that would define the framework's direction for years to come. By requiring Java 17 as a baseline and embracing Jakarta EE, this release signaled Spring's commitment to modernization and set the stage for innovative features that wouldn't have been possible with legacy constraints.

How to Upgrade to Spring Boot 3.0: JDK 17+ Requirement

The decision to require JDK 17 as a minimum wasn't just about keeping up with Java's release cadence; it was about unlocking a treasure trove of language features that make code more expressive and maintainable. Developers could now use records for DTOs, text blocks for multiline strings, pattern matching for instanceof checks, and sealed classes for domain modeling.

// Using Java Records for DTOs
public record UserDTO(String id, String name, String email) {}

// Pattern matching with instanceof
if (obj instanceof String s && s.length() > 5) {
    System.out.println(s.toUpperCase());
}

// Text blocks for readable SQL or JSON
String query = """
    SELECT u.id, u.name, u.email
    FROM users u
    WHERE u.created_at > ?
    ORDER BY u.name
    """;

Migrating from javax to Jakarta EE 9/10 in Spring Boot 3.0

The transition from javax.* to jakarta.* packages represented more than a simple namespace change; it was a critical step in the evolution of enterprise Java. This migration solved the long-standing issue of Java EE's stagnation under Oracle and embraced the community-driven Jakarta EE initiative.

// Before (Spring Boot 2.x)
import javax.servlet.http.HttpServletRequest;
import javax.persistence.Entity;
import javax.validation.constraints.NotNull;

// After (Spring Boot 3.0)
import jakarta.servlet.http.HttpServletRequest;
import jakarta.persistence.Entity;
import jakarta.validation.constraints.NotNull;

Spring Boot GraalVM Native Image Support: Complete Guide

Perhaps no feature better exemplifies Spring Boot 3.0's forward thinking approach than first class GraalVM native image support. This solved the long-standing challenge of Java's relatively slow startup times and high memory consumption, making Spring Boot applications viable for serverless environments and resource-constrained deployments.

# Build a native image
./mvnw -Pnative native:compile

# Run the native executable (starts in ~50ms vs ~2000ms for JVM)
./target/my-app

# Memory usage drops from ~300MB to ~50MB

The native image support includes AOT (Ahead-of-Time) processing that analyzes your application at build time:

@Configuration
@RegisterReflectionForBinding(UserDTO.class) // Hint for native image
public class AppConfig {
    // Configuration that works seamlessly in both JVM and native
}

Spring Boot 3.0 Observability with Micrometer: Enhanced Monitoring

Spring Boot 3.0 introduced a unified approach to observability through Micrometer's new Observation API. This solved the fragmentation problem where developers had to configure metrics, tracing, and logging separately, often with inconsistent implementations.

@RestController
public class UserController {
    private final ObservationRegistry registry;
    
    @GetMapping("/users/{id}")
    public User getUser(@PathVariable Long id) {
        return Observation.createNotStarted("user.fetch", registry)
            .lowCardinalityKeyValue("user.type", "regular")
            .observe(() -> userService.findById(id));
    }
}

Declarative HTTP Clients in Spring Boot 3.0: HTTP Interface Tutorial

Declarative HTTP clients arrived as a modern alternative to RestTemplate and WebClient, providing a type-safe, annotation-driven approach similar to Feign but with Spring's native support:

@Configuration
@EnableWebMvc
public class ClientConfig {
    @Bean
    public UserClient userClient() {
        WebClient webClient = WebClient.builder()
            .baseUrl("https://api.example.com")
            .build();
        HttpServiceProxyFactory factory = 
            HttpServiceProxyFactory.builder(WebClientAdapter.forClient(webClient))
            .build();
        return factory.createClient(UserClient.class);
    }
}

@HttpExchange("/api/users")
interface UserClient {
    @GetExchange("/{id}")
    User findById(@PathVariable Long id);
    
    @PostExchange
    User create(@RequestBody User user);
}

RFC 7807 Problem Details

Built-in support for standardized error responses solved the inconsistency problem in REST API error handling:

@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
    @ExceptionHandler(UserNotFoundException.class)
    ProblemDetail handleUserNotFound(UserNotFoundException e) {
        ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(
            HttpStatus.NOT_FOUND, e.getMessage());
        problemDetail.setTitle("User Not Found");
        problemDetail.setType(URI.create("https://api.example.com/errors/not-found"));
        return problemDetail;
    }
}

Spring Boot 3.1 (May 2023): Developer Experience Revolution

Spring Boot 3.1 focused intensively on improving the developer experience, particularly around local development and testing. This release recognized that developers spend most of their time in development and test environments, and optimized for those workflows.

Spring Boot Docker Compose Integration: Simplifying Local Development

The Docker Compose support eliminated the tedious process of manually starting and stopping development services. Spring Boot now automatically detects compose.yaml files and manages the lifecycle of defined services:

# compose.yaml in project root
services:
  postgres:
    image: postgres:15
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: user
      POSTGRES_PASSWORD: secret
    ports:
      - "5432:5432"
  
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
# application.properties
# Spring Boot automatically configures connections to these services
spring.docker.compose.enabled=true
spring.docker.compose.lifecycle-management=start_and_stop

Spring Boot Testcontainers Tutorial: @ServiceConnection Annotation

The @ServiceConnection annotation transformed integration testing by eliminating boilerplate container configuration:

@SpringBootTest
@Testcontainers
class IntegrationTest {
    
    @Container
    @ServiceConnection
    static PostgreSQLContainer<?> postgres = 
        new PostgreSQLContainer<>("postgres:15-alpine");
    
    @Container
    @ServiceConnection
    static GenericContainer<?> redis = 
        new GenericContainer<>("redis:7-alpine")
            .withExposedPorts(6379);
    
    @Test
    void contextLoads() {
        // Containers are automatically started and configured
        // No need for @DynamicPropertySource or manual configuration
    }
}

Spring Authorization Server

The production-ready OAuth 2.0 authorization server filled a critical gap left by Spring Security OAuth's deprecation:

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig {
    
    @Bean
    public RegisteredClientRepository registeredClientRepository() {
        RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
            .clientId("client")
            .clientSecret("{noop}secret")
            .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
            .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
            .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
            .redirectUri("http://localhost:8080/authorized")
            .scope(OidcScopes.OPENID)
            .build();
        
        return new InMemoryRegisteredClientRepository(registeredClient);
    }
}

Spring Boot 3.2 (November 2023): Performance and Modernization

Spring Boot 3.2 arrived with a laser focus on performance and modern Java features. With JDK 21's release bringing virtual threads out of preview, this version positioned Spring Boot at the forefront of Java's concurrency revolution.

Spring Boot 3.2 Virtual Threads: JDK 21 Performance Guide

Virtual threads represent the most significant change to Java concurrency since the introduction of the java.util.concurrent package. Spring Boot 3.2's support solved the age-old problem of thread-per-request architectures hitting scalability walls:

# Enable virtual threads with a single property
spring.threads.virtual.enabled=true
@RestController
public class HighConcurrencyController {
    
    @GetMapping("/process")
    public String processRequest() throws InterruptedException {
        // This can now handle 10,000+ concurrent requests
        // without 10,000 OS threads
        Thread.sleep(1000); // Simulating I/O operation
        return "Processed on: " + Thread.currentThread();
    }
}

// Before virtual threads: ~200 concurrent requests max
// After virtual threads: ~10,000+ concurrent requests easily

Spring Boot RestClient Tutorial: Modern Alternative to RestTemplate

RestClient emerged as the modern successor to RestTemplate, offering a fluent API without the reactive programming complexity of WebClient:

@Service
public class ApiService {
    private final RestClient restClient;
    
    public ApiService(RestClient.Builder builder) {
        this.restClient = builder
            .baseUrl("https://api.example.com")
            .defaultHeader("Accept", "application/json")
            .requestInterceptor((request, body, execution) -> {
                log.info("Calling: {}", request.getURI());
                return execution.execute(request, body);
            })
            .build();
    }
    
    public User fetchUser(Long id) {
        return restClient.get()
            .uri("/users/{id}", id)
            .retrieve()
            .onStatus(HttpStatusCode::is4xxClientError, (request, response) -> {
                throw new UserNotFoundException("User not found: " + id);
            })
            .body(User.class);
    }
}

Spring Boot JdbcClient: Simplified Database Access in 3.2

A modern, fluent alternative to JdbcTemplate that reduces boilerplate:

@Repository
public class UserRepository {
    private final JdbcClient jdbcClient;
    
    public UserRepository(JdbcClient jdbcClient) {
        this.jdbcClient = jdbcClient;
    }
    
    public Optional<User> findById(Long id) {
        return jdbcClient.sql("SELECT * FROM users WHERE id = :id")
            .param("id", id)
            .query(User.class)
            .optional();
    }
    
    public List<User> findByAge(int minAge) {
        return jdbcClient.sql("SELECT * FROM users WHERE age >= ?")
            .param(minAge)
            .query(User.class)
            .list();
    }
}

Dynamic SSL Certificate Reloading in Spring Boot 3.2

Dynamic SSL certificate reloading solved the operational nightmare of certificate rotation requiring application restarts:

spring:
  ssl:
    bundle:
      jks:
        server:
          key:
            alias: "server"
          keystore:
            location: "classpath:server.jks"
            password: "secret"
          reload-on-update: true  # Hot reload when certificate changes

Spring Boot Class Data Sharing (CDS): Faster Startup Times

CDS support dramatically improves startup time by sharing class metadata across JVM instances:

# Generate CDS archive
java -Dspring.context.exit=onRefresh -XX:ArchiveClassesAtExit=app.jsa -jar app.jar

# Run with CDS (30-50% faster startup)
java -XX:SharedArchiveFile=app.jsa -jar app.jar

Spring Boot 3.3 (May 2024): Security and Transparency

Spring Boot 3.3 emphasized security, transparency, and operational excellence. With increasing focus on supply chain security and compliance requirements, this release provided tools to understand and secure application dependencies.

CDS (Class Data Sharing) Support Enhancement

Building on 3.2's foundation, CDS support was refined to be more automatic and easier to use in containerized environments.

Enhanced Spring Boot Observability in 3.3: Zero Configuration Monitoring

Extended observability coverage to more Spring components with zero configuration:

// Automatic observation for Spring Data repositories
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    // All methods are automatically observed
    List<User> findByAgeGreaterThan(int age);
}

// Custom observations with more context
@Component
public class OrderService {
    private final ObservationRegistry registry;
    
    public Order processOrder(Order order) {
        return Observation.createNotStarted("order.processing", registry)
            .contextualName("process-order")
            .lowCardinalityKeyValue("order.type", order.getType())
            .highCardinalityKeyValue("order.id", order.getId())
            .observe(() -> {
                // Business logic here
                return orderRepository.save(order);
            });
    }
}

Spring Boot SBOM Actuator: Software Bill of Materials for Security

The SBOM endpoint provides transparency into application dependencies, crucial for security audits and compliance:

# Get SBOM in CycloneDX format
curl http://localhost:8080/actuator/sbom

# Returns detailed dependency information
{
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "components": [
    {
      "type": "library",
      "name": "spring-boot",
      "version": "3.3.0",
      "licenses": [{"license": {"name": "Apache-2.0"}}]
    }
  ]
}

Spring Boot Service Connections: Enhanced Testing with Multiple Services

Service connections were extended to support more services and testing scenarios:

@SpringBootTest
class MultiServiceIntegrationTest {
    
    @Container
    @ServiceConnection
    static MongoDBContainer mongodb = new MongoDBContainer("mongo:6");
    
    @Container
    @ServiceConnection
    static KafkaContainer kafka = new KafkaContainer(
        DockerImageName.parse("confluentinc/cp-kafka:latest"));
    
    @Container
    @ServiceConnection(name = "redis-cache")
    static GenericContainer<?> redis = new GenericContainer<>("redis:7-alpine")
        .withExposedPorts(6379);
}

Base64 Resource Support in Spring Boot Configuration

Native support for Base64-encoded resources simplified handling of certificates and sensitive data in configuration:

app:
  ssl:
    # Inline certificate as Base64
    certificate: base64:LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNVakNDQWJz...
  
  encryption:
    # Inline key material
    public-key: base64:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQ...

# Reference in code
@Value("${app.ssl.certificate}")
private Resource certificate;

Spring Boot 3.4 (November 2024): Operational Excellence

Spring Boot 3.4 focused on operational maturity, recognizing that modern applications need sophisticated logging, resilient patterns, and cloud-native compatibility.

Spring Boot Structured Logging: JSON Logs for Cloud Native Applications

Native structured logging support solved the challenge of parsing logs in modern observability platforms:

# Enable structured JSON logging
logging.structured.format.console=ecs
logging.structured.format.file=logstash

# Or use custom format
logging.pattern.console={"timestamp":"%d","level":"%level","message":"%msg"}%n
@Component
public class UserService {
    private static final Logger log = LoggerFactory.getLogger(UserService.class);
    
    public void processUser(String userId, String action) {
        // Structured logging with MDC
        try (MDC.MDCCloseable closeable = MDC.putCloseable("user.id", userId)) {
            log.info("Processing user action", 
                kv("action", action),
                kv("timestamp", Instant.now()),
                kv("processing.time.ms", 150));
        }
    }
}

// Output:
{
  "timestamp": "2024-11-15T10:30:00Z",
  "level": "INFO",
  "logger": "com.example.UserService",
  "message": "Processing user action",
  "user.id": "user-123",
  "action": "UPDATE_PROFILE",
  "processing.time.ms": 150
}

Spring Boot @Fallback Annotation: Graceful Degradation Pattern

The @Fallback annotation provides elegant handling of optional dependencies and graceful degradation:

@Configuration
public class DataSourceConfig {
    
    @Bean
    @Primary
    @ConditionalOnProperty("app.database.primary.enabled")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create()
            .url("jdbc:postgresql://prod-db:5432/myapp")
            .build();
    }
    
    @Bean
    @Fallback  // Only used if primary isn't available
    public DataSource fallbackDataSource() {
        log.warn("Using in-memory database as fallback");
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.H2)
            .addScript("schema.sql")
            .build();
    }
}

Spring Boot MockMvc with AssertJ: Improved Testing Experience

Enhanced testing experience with fluent assertions:

@SpringBootTest
@AutoConfigureMockMvc
class UserControllerTest {
    
    @Autowired
    private MockMvc mockMvc;
    
    @Test
    void testUserEndpoint() throws Exception {
        assertThat(mockMvc.perform(post("/users")
                .contentType(MediaType.APPLICATION_JSON)
                .content("""
                    {
                        "name": "John Doe",
                        "email": "[email protected]"
                    }
                    """)))
            .hasStatus(HttpStatus.CREATED)
            .hasContentType(MediaType.APPLICATION_JSON)
            .bodyJson()
                .extractingPath("$.id").isNotNull()
                .extractingPath("$.name").isEqualTo("John Doe")
                .extractingPath("$.email").isEqualTo("[email protected]");
    }
}

Virtual Thread Configuration in Spring Boot 3.4: Advanced Setup

Building on 3.2's foundation, virtual thread support was extended to more components:

@Configuration
@EnableAsync
public class AsyncConfig {
    
    @Bean
    public TaskExecutor taskExecutor() {
        // Virtual thread executor for @Async methods
        return new TaskExecutorAdapter(Executors.newVirtualThreadPerTaskExecutor());
    }
    
    @Bean
    @ConditionalOnProperty("spring.threads.virtual.enabled")
    public TomcatProtocolHandlerCustomizer<?> protocolHandlerVirtualThreadCustomizer() {
        return protocolHandler -> {
            protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
        };
    }
}

Spring Boot ARM Support: Building Multi-Architecture Docker Images

Official ARM support solved deployment challenges on Apple Silicon and ARM-based cloud instances:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <image>
            <buildpacks>
                <buildpack>paketobuildpacks/java</buildpack>
            </buildpacks>
            <platforms>
                <platform>linux/amd64</platform>
                <platform>linux/arm64</platform>
            </platforms>
        </image>
    </configuration>
</plugin>

Spring Boot 3.5 (May 2025): The Grand Finale

Spring Boot 3.5, as the final minor release in the 3.x series, focuses on operational polish and preparing applications for the future. It addresses the remaining gaps in observability, configuration management, and operational control.

Spring Boot SSL Certificate Monitoring: Metrics and Alerts

Comprehensive SSL certificate monitoring prevents the all-too-common production outage from expired certificates:

// Automatically exposed metrics:
// - ssl.bundle.validity.days (days until expiration)
// - ssl.bundle.expiry.timestamp
// - ssl.bundle.reload.count
// - ssl.bundle.reload.failure

@Component
public class CertificateMonitor {
    private final MeterRegistry meterRegistry;
    
    @EventListener
    public void onSslBundleReload(SslBundleReloadEvent event) {
        Gauge.builder("ssl.certificate.days_until_expiry", 
            () -> event.getBundle().getDaysUntilExpiry())
            .tag("bundle", event.getBundleName())
            .register(meterRegistry);
        
        // Alert if certificate expires in less than 30 days
        if (event.getBundle().getDaysUntilExpiry() < 30) {
            alertingService.sendCertificateExpiryWarning(event.getBundleName());
        }
    }
}

Spring Boot Environment Variables: Loading JSON Configuration

Direct JSON property loading from environment variables simplifies cloud deployments:

# Set complex configuration via environment variable
export SPRING_APPLICATION_JSON='{
  "server": {"port": 8080},
  "spring": {
    "datasource": {
      "url": "jdbc:postgresql://localhost:5432/mydb",
      "username": "user"
    }
  },
  "app": {
    "features": ["feature1", "feature2"],
    "cache": {"ttl": 3600}
  }
}'

# Or use individual JSON properties
export APP_CONFIG='{"timeout": 30, "retries": 3}'
@ConfigurationProperties(prefix = "app")
public class AppProperties {
    private Map<String, Object> config;
    // Automatically populated from APP_CONFIG environment variable
}

Spring Boot Quartz Actuator: Trigger Scheduled Jobs via REST API

Operational flexibility to manually trigger scheduled jobs without waiting for their schedule:

# List all Quartz jobs
curl http://localhost:8080/actuator/quartz/jobs

# Get job details
curl http://localhost:8080/actuator/quartz/jobs/reportGeneration/daily-report

# Manually trigger a job
curl -X POST http://localhost:8080/actuator/quartz/jobs/reportGeneration/daily-report/trigger

# Trigger with custom data
curl -X POST http://localhost:8080/actuator/quartz/jobs/data-sync/trigger \
  -H "Content-Type: application/json" \
  -d '{"source": "manual", "priority": "high"}'
@Component
public class ReportJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        // This can now be triggered via actuator endpoint
        String trigger = context.getTrigger().getKey().getName();
        if ("MANUAL".equals(trigger)) {
            log.info("Job manually triggered via actuator");
        }
        generateReport();
    }
}

Spring Boot ECS Structured Logging: Nested JSON Format Guide

Enhanced structured logging with nested JSON for better compatibility with modern log aggregation systems:

logging.structured.format.console=ecs
logging.structured.ecs.service.name=my-service
logging.structured.ecs.service.version=${project.version}
logging.structured.ecs.service.environment=${spring.profiles.active}
@RestController
public class OrderController {
    private static final Logger log = LoggerFactory.getLogger(OrderController.class);
    
    @PostMapping("/orders")
    public Order createOrder(@RequestBody Order order) {
        log.info("Creating order", 
            kv("event.action", "order.create"),
            kv("event.category", "process"),
            kv("order", Map.of(
                "id", order.getId(),
                "amount", order.getAmount(),
                "items", order.getItems().size()
            )),
            kv("user", Map.of(
                "id", getCurrentUserId(),
                "role", getCurrentUserRole()
            ))
        );
        return orderService.create(order);
    }
}

// Output:
{
  "@timestamp": "2025-05-01T10:30:00.123Z",
  "log.level": "INFO",
  "message": "Creating order",
  "ecs": {
    "version": "8.6"
  },
  "service": {
    "name": "my-service",
    "version": "3.5.0",
    "environment": "production"
  },
  "event": {
    "action": "order.create",
    "category": "process"
  },
  "order": {
    "id": "ORD-12345",
    "amount": 299.99,
    "items": 3
  },
  "user": {
    "id": "USER-789",
    "role": "customer"
  }
}

Conclusion: Spring Boot 3.x Migration Guide and Future Roadmap

The Spring Boot 3.x series will be remembered as the generation that modernized Java application development for the cloud native era. From the bold decision to require Java 17 in 3.0 to the operational refinements in 3.5, each release has systematically addressed the real challenges developers face in building, testing, deploying, and operating applications at scale.

Key Achievements of Spring Boot 3.x Series

Performance Revolution: Virtual threads and native images transformed Java from a memory hungry, slow starting platform to one that can compete with Go and Rust in cloud environments

Developer Experience: Docker Compose integration, Testcontainers support, and declarative HTTP clients eliminated countless hours of boilerplate and configuration

Operational Excellence: Structured logging, comprehensive observability, and SSL certificate management addressed the critical needs of production systems

Modern Java Embrace: By requiring Java 17 and quickly adopting Java 21 features, Spring Boot ensured developers could use the latest language improvements

Preparing for Spring Boot 4.0 (November 2025)

As we prepare for Spring Boot 4.0 in November 2025, the 3.x series has laid an incredibly strong foundation. The framework has evolved from being merely a convention over configuration tool to a comprehensive platform that addresses the entire application lifecycle from the first line of code to production monitoring.

The journey from 3.0 to 3.5 demonstrates Spring Boot's commitment to solving real problems rather than chasing trends. Whether you're building microservices, serverless functions, or traditional applications, Spring Boot 3.x provides the tools, performance, and operational capabilities needed for modern Java development.

Frequently Asked Questions (FAQ)

Q: Should I upgrade to Spring Boot 3.x from 2.x? A: Yes, if you can meet the Java 17 requirement. The performance improvements, especially with virtual threads and native images, make it worthwhile.

Q: What's the biggest breaking change in Spring Boot 3.0? A: The migration from javax to jakarta packages requires updating all imports in your codebase.

Q: Can I use Spring Boot 3.x with Java 11? A: No, Spring Boot 3.x requires Java 17 as a minimum. For Java 11 support, you'll need to stay on Spring Boot 2.7.

Q: When will Spring Boot 4.0 be released? A: Spring Boot 4.0 is scheduled for release in November 2025.

Q: How do I enable virtual threads in Spring Boot? A: Simply add spring.threads.virtual.enabled=true to your application properties (requires Java 21+).

As we bid farewell to the 3.x series, we look forward to seeing how Spring Boot 4.0 will build upon this remarkable foundation to push Java application development even further into the future.


Last updated: September 2025 | Spring Boot 3.5 is the final minor release in the 3.x series

Subscribe to my newsletter.

Sign up for my weekly newsletter and stay up to date with current blog posts.

Weekly Updates
I will send you an update each week to keep you filled in on what I have been up to.
No spam
You will not receive spam from me and I will not share your email address with anyone.