Backing data for the streaming results in ../soak-results.md. Setup: 1-CPU/1-Gi grpc-jvm pod, driver (clj-grpc.soak.stream-driver) on its own worker, persistent bidi Chat streams, absolute-schedule open-loop pacing, bounded in-flight (256/stream), per-message client-side latency. First step of every run is JIT warmup (fresh pods) — excluded from conclusions.
Streaming capacity (2026-08-30, bidi Chat echo, same grpc-jvm pod, raw
tables in results/): streaming moves ~15,000–16,000 msg/s on one core
— ~7.5× the unary gRPC plateau and ~16× REST — with per-message p50 under
2 ms and p99 under 30 ms through 8,000 msg/s. The executors split decisively
at streaming's limits: :executor :direct holds p99 2–2.5× lower than the
VT default at every rate above 6,000 and keeps delivering at 16,000
(38 deferred/s vs VT's 625/s) — the per-message dispatch the VT executor
still pays is the one cost streaming cannot amortize. Full doctrine across
every measured regime: VT wins only low-utilization unary tails; :direct
wins high-load unary, all streaming, capacity, and CPU — provided handlers
never block. And the library's oldest guidance is now cluster-quantified:
one stream really does beat N unaries, by ~7.5× per core.
| offered msg/s | sent/s | echoed/s | p50ms | p99ms | p999ms | deferred/s |
|---|
| 400 | 400.0 | 400.0 | 3.34 | 2460.29 | 2460.29 | 0.0 |
| 800 | 800.0 | 800.0 | 2.47 | 8.22 | 14.97 | 0.0 |
| 1200 | 1200.2 | 1200.2 | 2.47 | 8.22 | 14.97 | 0.0 |
| 1600 | 1600.0 | 1600.0 | 2.47 | 8.22 | 20.21 | 0.0 |
| 2000 | 2000.0 | 2000.0 | 1.83 | 8.22 | 20.21 | 0.0 |
| 2400 | 2400.2 | 2400.2 | 1.83 | 8.22 | 14.97 | 0.0 |
| 2800 | 2800.2 | 2800.2 | 1.83 | 8.22 | 27.29 | 0.0 |
| 3200 | 3200.0 | 3200.0 | 1.83 | 8.22 | 14.97 | 0.0 |
| 3600 | 3600.2 | 3600.2 | 1.83 | 11.09 | 27.29 | 0.0 |
| 4000 | 4000.0 | 4000.0 | 1.83 | 8.22 | 14.97 | 0.0 |
| 4400 | 4400.2 | 4400.2 | 1.83 | 11.09 | 20.21 | 0.0 |
| 4800 | 4800.2 | 4800.2 | 1.83 | 11.09 | 27.29 | 0.0 |
| offered msg/s | sent/s | echoed/s | p50ms | p99ms | p999ms | deferred/s |
|---|
| 400 | 400.0 | 400.0 | 3.34 | 1822.43 | 2460.29 | 0.0 |
| 800 | 800.0 | 800.0 | 2.47 | 11.09 | 122.36 | 0.0 |
| 1200 | 1200.2 | 1200.2 | 2.47 | 8.22 | 14.97 | 0.0 |
| 1600 | 1600.0 | 1600.0 | 1.83 | 8.22 | 11.09 | 0.0 |
| 2000 | 2000.0 | 2000.0 | 1.83 | 8.22 | 14.97 | 0.0 |
| 2400 | 2400.2 | 2400.2 | 2.47 | 8.22 | 14.97 | 0.0 |
| 2800 | 2800.2 | 2800.2 | 1.83 | 8.22 | 20.21 | 0.0 |
| 3200 | 3200.0 | 3200.0 | 1.36 | 8.22 | 20.21 | 0.0 |
| 3600 | 3600.2 | 3600.2 | 1.83 | 11.09 | 49.73 | 0.0 |
| 4000 | 4000.0 | 4000.0 | 1.83 | 8.22 | 14.97 | 0.0 |
| 4400 | 4400.2 | 4400.2 | 1.83 | 11.09 | 20.21 | 0.0 |
| 4800 | 4800.2 | 4800.2 | 1.83 | 11.09 | 27.29 | 0.0 |
| offered msg/s | sent/s | echoed/s | p50ms | p99ms | p999ms | deferred/s |
|---|
| 4000 | 3154.9 | 3154.9 | 4.51 | 20105.83 | 20105.83 | 845.1 |
| 6000 | 6000.3 | 6000.3 | 2.47 | 27.29 | 67.14 | 0.0 |
| 8000 | 8000.0 | 8000.0 | 3.34 | 27.29 | 67.14 | 0.0 |
| 10000 | 10000.0 | 10000.0 | 4.51 | 90.64 | 122.36 | 0.0 |
| 12000 | 12000.3 | 12000.3 | 4.51 | 165.19 | 301.06 | 0.0 |
| 14000 | 14000.3 | 14000.3 | 11.09 | 406.43 | 406.43 | 0.0 |
| 16000 | 15375.1 | 15375.1 | 27.29 | 1349.95 | 2460.29 | 625.0 |
| offered msg/s | sent/s | echoed/s | p50ms | p99ms | p999ms | deferred/s |
|---|
| 4000 | 3641.0 | 3641.0 | 2.47 | 14893.21 | 14893.21 | 359.0 |
| 6000 | 6000.3 | 6000.3 | 1.83 | 14.97 | 27.29 | 0.0 |
| 8000 | 8000.0 | 8000.0 | 2.47 | 20.21 | 90.64 | 0.0 |
| 10000 | 10000.0 | 10000.0 | 3.34 | 49.73 | 122.36 | 0.0 |
| 12000 | 12000.3 | 12000.3 | 3.34 | 67.14 | 122.36 | 0.0 |
| 14000 | 14000.3 | 14000.3 | 4.51 | 165.19 | 301.06 | 0.0 |
| 16000 | 15961.7 | 15961.7 | 11.09 | 740.71 | 740.71 | 38.3 |