Spring Boot: From Basics to Production · Deployment and Performance
Virtual Threads
Handle more concurrent blocking requests with Java 21 virtual threads.
Virtual threads (Java 21) are lightweight threads managed by the JVM; blocking I/O parks them cheaply instead of tying up OS threads. Enable them with spring.threads.virtual.enabled=true (Boot 3.2+) so Tomcat, @Async and schedulers use virtual threads. They help I/O-bound, blocking code (JDBC, RestClient) scale to many concurrent requests without reactive programming — but downstream limits (database connection pools) still apply.
# application.yml
spring:
threads:
virtual:
enabled: true
datasource:
hikari:
maximum-pool-size: 30 # the real concurrency limit for DB work
// Bound concurrency to a downstream service explicitly
private final Semaphore pricingLimit = new Semaphore(50);
Price price(String sku) throws InterruptedException {
pricingLimit.acquire();
try { return pricingClient.get(sku); } finally { pricingLimit.release(); }
}
Common pitfalls
- Expecting virtual threads to speed up CPU-bound work.
- Unlimited concurrency overwhelming databases and APIs (use pools/semaphores).
- Pinning: long blocking inside
synchronizedblocks on older JDKs (improved in JDK 24).
Key points
- Cheap blocking for I/O-bound apps
- One property to enable in Boot
- Downstream limits still apply
Further reading: Spring Boot: Task execution (virtual threads)
Practice questions
Do virtual threads make a CPU-heavy endpoint faster?
Answer
No. They make blocking I/O cheap so more requests can wait concurrently; CPU-bound work is still limited by cores.
Why is the database pool still important with virtual threads?
Answer
Thousands of virtual threads may want connections at once; the pool caps concurrent queries to what the database can handle.
Open in the app to mark lessons complete, take notes and track your progress.