Oracle explicitly says virtual threads improve throughput rather than latency, should not be pooled, and scarce downstream resources should still have explicit concurrency limits. A database connection pool itself acts as such a limit.
Imagine a Spring Boot payment API handling:
2,000 requests/sec
Database pool:
100 connections
Normal DB time:
20 ms
Simplified capacity:
100 ÷ 0.020 ≈ 5,000 ops/sec
Everything is fine.
Now PostgreSQL slows to:
250 ms
New capacity:
100 ÷ 0.250 ≈ 400 ops/sec
Traffic is still:
2,000 requests/sec
So roughly:
1,600 requests/sec start waiting
After just 10 seconds:
1,600 × 10 = 16,000 waiting requests
Virtual threads can hold those waiting tasks cheaply.
But PostgreSQL still has only 100 connections.
Practical failure mode
The pool fills.
Requests wait longer.
Some hit their timeout.
Clients retry.
Those retries create even more waiting work.
Now the service can enter a feedback loop:
DB slowdown → pool saturation → timeouts → retries → more load → worse saturation
That is the real danger.
Virtual threads scale waiting.
They do not scale the database.
Protect the actual bottleneck with:
- bounded connection pools
- short timeouts
- controlled retries with jitter
- load shedding 10,000 virtual threads ≠ 10,000 database operations.

Top comments (0)