| Spring MVC | Spring WebFlux | |
|---|---|---|
| Model | Thread-per-request (blocking) | Non-blocking, event-driven |
| Server | Tomcat/Jetty (Servlet) | Netty (default) |
| Return type | Direct value (User, List<User>) | Mono<T> / Flux<T> |
| Library compat | JPA, Hibernate, JDBC | R2DBC, ReactiveMongoTemplate |
| Concurrency | ~5K (thread pool limit) | 100K+ với thread pool nhỏ |
| Debug | Stack trace rõ | Khó hơn (async chain) |
// MVC
@GetMapping("/user/{id}")
User get(@PathVariable Long id) { return repo.findById(id).orElseThrow(); }
// WebFlux
@GetMapping("/user/{id}")
Mono<User> get(@PathVariable Long id) { return repo.findById(id); }Khi chọn WebFlux:
- High-concurrency I/O-bound (chat, streaming, SSE).
- Microservice gateway forward nhiều request đồng thời.
- Backpressure cần thiết (stream dữ liệu lớn).
Khi giữ MVC:
- CPU-bound task (WebFlux không giúp).
- Dùng JPA/Hibernate (chưa có reactive equivalent).
- Team chưa quen reactive — debug Mono/Flux khó.
2026 quan trọng: Virtual Threads (Java 21) cho phép Spring MVC đạt concurrency tương đương WebFlux mà giữ code đồng bộ → nhiều team quay về MVC. Bật bằng spring.threads.virtual.enabled=true.
| Spring MVC | Spring WebFlux | |
|---|---|---|
| Model | Thread-per-request (blocking) | Non-blocking, event-driven |
| Server | Tomcat/Jetty (Servlet) | Netty (default) |
| Return type | Direct value (User, List<User>) | Mono<T> / Flux<T> |
| Library compat | JPA, Hibernate, JDBC | R2DBC, ReactiveMongoTemplate |
| Concurrency | ~5K (thread pool limit) | 100K+ with a small thread pool |
| Debug | Clear stack traces | Harder (async chains) |
// MVC
@GetMapping("/user/{id}")
User get(@PathVariable Long id) { return repo.findById(id).orElseThrow(); }
// WebFlux
@GetMapping("/user/{id}")
Mono<User> get(@PathVariable Long id) { return repo.findById(id); }Choose WebFlux when:
- High-concurrency I/O-bound (chat, streaming, SSE).
- Microservice gateways forwarding many requests concurrently.
- You need backpressure (streaming large data).
Stick with MVC when:
- CPU-bound tasks (WebFlux does not help).
- You use JPA/Hibernate (no mature reactive equivalent).
- The team is unfamiliar with reactive — debugging Mono/Flux is hard.
Important in 2026: Virtual Threads (Java 21) let Spring MVC reach WebFlux-like concurrency while keeping synchronous code → many teams return to MVC. Enable with spring.threads.virtual.enabled=true.