Spring Boot is the most widely deployed Java web framework in enterprise software, and in 2026 it is also competitive for greenfield microservices work thanks to two changes: virtual threads (Project Loom) making blocking code scale without async complexity, and GraalVM native image bringing startup times under 100 ms. If you work in Java or Kotlin and need to build production services, Spring Boot 3.4 is the pragmatic, well-supported choice.
What changed in 2026
- Virtual threads on by default. Spring Boot 3.4 enables
spring.threads.virtual.enabled=true by default. Your existing blocking JDBC calls, RestTemplate requests, and @Service methods now run on virtual threads — millions of concurrent requests without thread-pool tuning.
- Spring Boot 3.4 requires Java 21+. JDK 21 LTS is the minimum. This means pattern matching (
switch expressions, records, sealed classes) are first-class Java, not preview features.
- Spring Modulith 1.2 stable. Modular monolith patterns with eventing between modules — the practical middle ground between monolith and microservices.
- Spring AI 1.0 GA. First-class Spring integration with OpenAI, Anthropic, and local models (Ollama). Vector store support for pgvector and Chroma.
Project setup
Go to start.spring.io and select:
- Project: Gradle (Kotlin DSL) or Maven
- Language: Java (or Kotlin)
- Spring Boot: 3.4.x
- Dependencies: Spring Web, Spring Data JPA, PostgreSQL Driver, Spring Security, Validation
Or via the CLI:
curl https://start.spring.io/starter.zip \
-d type=gradle-project \
-d language=java \
-d bootVersion=3.4.3 \
-d dependencies=web,data-jpa,postgresql,security \
-d javaVersion=21 \
-o demo.zip && unzip demo.zip
The core programming model
Spring Boot auto-configures beans based on what is on the classpath. You declare components; the framework wires them:
// Entity
@Entity
@Table(name = "posts")
public record Post(
@Id @GeneratedValue Long id,
@Column(nullable = false) String title,
boolean published
) {}
// Repository — no implementation needed
public interface PostRepository extends JpaRepository<Post, Long> {
List<Post> findByPublishedTrue();
}
// Service
@Service
@Transactional(readOnly = true)
public class PostService {
private final PostRepository repo;
PostService(PostRepository repo) { this.repo = repo; } // constructor injection
public List<Post> published() { return repo.findByPublishedTrue(); }
}
// Controller
@RestController
@RequestMapping("/api/posts")
public class PostController {
private final PostService service;
PostController(PostService service) { this.service = service; }
@GetMapping
public List<Post> list() { return service.published(); }
}
Running this with ./gradlew bootRun produces a running API at http://localhost:8080/api/posts.
Virtual threads in practice
# application.properties
spring.threads.virtual.enabled=true
spring.datasource.hikari.maximum-pool-size=20
With virtual threads, 20 database connections serve thousands of concurrent requests — the JVM creates a new virtual thread (lightweight, ~1 KB) per request instead of blocking a platform thread. No Mono, no Flux, no reactive operators required.
Configuration and profiles
# application.yml
spring:
datasource:
url: jdbc:postgresql://localhost:5432/mydb
username: ${DB_USER}
password: ${DB_PASS}
jpa:
show-sql: true # remove in production
hibernate:
ddl-auto: validate # never "create-drop" in production
---
spring:
config:
activate:
on-profile: prod
jpa:
show-sql: false
Framework comparison
| Factor |
Spring Boot |
Quarkus |
Micronaut |
| Ecosystem |
Largest |
Growing |
Moderate |
| Native image |
GraalVM (good) |
Excellent |
Good |
| Virtual threads |
Yes (3.2+) |
Yes |
Yes |
| Learning curve |
High (rich) |
Moderate |
Moderate |
| Enterprise adoption |
Dominant |
Growing |
Niche |
How to pick
Use Spring Boot when your organisation already deploys it, when you need the Spring Security ecosystem (OAuth2, SAML, LDAP), or when you are writing a long-running JVM service where startup time does not matter. Use Quarkus for Kubernetes-native work where native image startup time is critical.
Common mistakes
Using @Autowired field injection. Constructor injection is preferred — it makes dependencies explicit and enables immutable beans. @Autowired on a field hides dependencies.
ddl-auto: create-drop in any shared environment. This drops and recreates your database schema on every restart. Use Flyway or Liquibase for migrations; set ddl-auto: validate.
Catching Exception everywhere. Use @ControllerAdvice with @ExceptionHandler to centralise error handling rather than wrapping every service call in try/catch.
Missing @Transactional on write operations. Without @Transactional, each ORM operation is its own transaction. Multi-step writes that fail halfway leave partial data.
What to skip
- Spring MVC XML config.
applicationContext.xml is a relic of Spring 2. Annotation and Java config replaced it; do not learn it.
- Spring WebFlux (Project Reactor) for new services. Virtual threads give you the scalability of reactive without the cognitive overhead of
Mono/Flux. Use WebFlux only if you need backpressure or streaming responses.
RestTemplate. It is deprecated in Spring Boot 3. Use RestClient (synchronous, fluent) or WebClient (reactive) for HTTP calls.
FAQ
Spring Boot vs Quarkus in 2026?
Spring Boot for teams with existing Spring investment and complex security needs. Quarkus for Kubernetes-native workloads where native image performance matters most.
Do I need to know Spring Core before Spring Boot?
You should understand dependency injection, beans, and the application context. Spring Boot auto-configuration hides most of it, but when something goes wrong, you need the mental model to debug it.
Kotlin or Java with Spring Boot?
Kotlin is fully supported and removes a lot of Java verbosity (data classes replace records for mutable models, extension functions, coroutines for async). New teams often prefer Kotlin.
How do I deploy to Kubernetes?
./gradlew bootBuildImage produces an OCI-compliant container via Cloud Native Buildpacks — no Dockerfile required for standard apps. Then apply your Kubernetes manifests.
Where to go next
After Spring Boot basics, explore how to containerize an app in 2026 for Docker and Kubernetes deployment, how to build a REST API in 2026 for API design principles, and how to set up a database in 2026 for production PostgreSQL configuration.