Skip to content
github-actions[bot] edited this page Sep 10, 2026 · 155 revisions

Performance

Throughput and footprint of Titanium as a reverse / edge proxy and as a decrypting (MITM) proxy, measured on the same harness against YARP, nginx, HAProxy, and Envoy where each OS can run them.

RPS is requests per second (gRPC charts use RPC/s). Numbers are Release builds on matched GitHub-hosted runners: Windows and Linux at 4 vCPU / 16 GiB, macOS at macos-15-intel 4-core / 14 GB. Read within one chart or table — absolute RPS is not comparable across operating systems. Not possible means that product cannot run that path on that OS; Not measured means the path exists but no published number yet.

For pooling knobs and certificate first-visit tuning, see Performance and pooling. Laptop cool A/B tables (not publishable) live on Performance Local Lab.

Why this comparison is fair

  • Same load generator, same origin process, and the same warmup / measure windows (2s / 8s) with the same concurrency ramp (8, 16, 32, 64).
  • Every reverse arm is three OS processes: load generator + origin + proxy. Origin-direct omits the proxy; peers are never in-process with the client.
  • Same runner class per table (windows-latest / ubuntu-latest / macos-15-intel). Laptop numbers are never mixed into these tables.
  • Peers use equivalent TLS/ALPN and streaming-friendly settings on the same loopback shape. HAProxy and Envoy are Linux/macOS only — Windows cells are Not possible.
  • MITM (HTTPS decryption with forged certificates) is Titanium-only; peers cannot MITM. Those tables show Titanium MITM overhead versus its own reverse path on the same wires.
  • Tiny keep-alive GET (~56-byte JSON) is the industry RPS shape (same class as wrk / TechEmpower). It is also real for small JSON APIs and health checks.
  • Same-protocol H2↔H2 / H3↔H3 on that shape is Titanium’s best case: with interception off, Titanium copies frames instead of decoding and re-encoding headers (peers do a full HTTP decode). Medals there are not the typical reverse-proxy job.
  • Typical reverse is H1 TLS→H1 or H2→H1 (~1.1× YARP on tiny GET). With larger bodies, see Heavier reverse: at 64 KiB H2 TLS→H2 TLS, Titanium is behind YARP (~0.69–0.76×).

How to read the tables

  • Sustain = last concurrency that still met error/latency SLOs. Peak = highest RPS in that ramp.
  • 🥇 = best among Titanium / nginx / YARP on Reverse rows (highest RPS; on a tie, lower memory then lower CPU%). Gold medals are per cell on tiny GET — an H2↔H2 gold is that frame-copy best case, not “Titanium is 1.7× on all reverse.” For larger-body H2→H2, see the heavier tables.
  • MITM tables are Titanium-only. Lite÷Reverse / Full÷Reverse = Titanium MITM sustain ÷ Titanium reverse sustain on the same Client×Origin pair — the overhead of decrypting and intercepting versus bare reverse, not versus nginx or YARP.
  • Not possible = cannot do that path. Not measured = path exists but no published number yet.

Contents

Measurement environment

All three OS use the 4-core-class public-repo GitHub-hosted runners: Windows / Linux at 4 vCPU / 16 GiB / 14 GB SSD, macOS at macos-15-intel 4-core / 14 GB (not macos-latest). Same harness knobs: warmup 2s / measure 8s; concurrency 8, 16, 32, 64; median of 3 repeats. Prefer Titanium÷YARP / Titanium÷nginx ratios over absolute RPS.

Laptop High-perf / cool-paired Windows numbers live on Performance Local Lab. Do not mix those absolutes into the tables below.

Windows (GitHub-hosted windows-latest)

OS Windows Server (GitHub-hosted windows-latest)
CPU 4 logical processors
RAM 16 GiB
Runtime .NET 10.0.x
nginx nginx/Windows 1.31.3 (same-OS only; no QUIC)
HAProxy Not possible on Windows (no official port)
Envoy Not possible on Windows (upstream discontinued Windows builds)
YARP Yarp.ReverseProxy 2.3.0
Harness RpsLoadProbe Release; median of 3 repeats

Linux (GitHub-hosted ubuntu-latest)

OS Ubuntu 24.04.x LTS
CPU 4 logical processors (AMD EPYC; runners this pass were 7763 / 9V74)
RAM 16 GiB
Runtime .NET 10.0.11
nginx nginx/1.31.4 (nginx.org mainline, --with-http_v3_module)
HAProxy HAProxy 3.2.23 built with USE_QUIC (GHA; Ubuntu distro 2.8 is not QUIC-capable)
Envoy pinned GitHub release static binary 1.36.7 (HTTP/3 compiled in)
YARP Yarp.ReverseProxy 2.3.0
Harness RpsLoadProbe Release; median of 3 repeats where noted

macOS (GitHub-hosted macos-15-intel)

OS macOS 15 (GitHub-hosted macos-15-intel, Intel x86_64)
CPU 4 logical processors
RAM 14 GB
Runtime .NET 10.0.x
nginx Homebrew nginx with --with-http_v3_module (workflow fails if missing)
HAProxy Homebrew haproxy with USE_QUIC (workflow fails if missing; 3.2.23 osx source fallback)
Envoy Homebrew bottle when present; else pinned darwin-amd64 1.36.7 (official GitHub assets are Linux-only). HTTP/3 compiled in.
MsQuic Homebrew libmsquic + openssl@3 on DYLD_LIBRARY_PATH / DYLD_FALLBACK_LIBRARY_PATH (QuicListener.IsSupported)
YARP Yarp.ReverseProxy 2.3.0
Harness RpsLoadProbe Release; median of 3 repeats where noted

Do not use macos-latest (Apple Silicon, 3-core / 7 GB) for publishable saturation numbers.

Saturation control

Calibration for the shared 4 vCPU loopback shape: how close client + origin are to saturated before ranking reverse peers. Tiny keep-alive GET. Median of 3 repeats @ 9a2b3a1e34441539402. Warmup 2s / measure 8s; concurrency 8, 16, 32, 64. Block A % of origin-HttpClient uses median peak RPS. Blocks B/C use peer÷YARP / ÷nginx on median peak (not % of H1 origin). RPS cells embed median RSS / CPU for the proxy child plus its full descendant tree (serve-proxy → nginx master → workers); origin-direct samples the origin child. Product matrices below use matched dotnet-httpclient only (not bombardier).

Block A — H1 plain

Arm Generator Notes
origin-direct dotnet-httpclient No proxy — origin ceiling under the same client used for publishable ratios
origin-direct-bombardier bombardier External client check (CI installs bombardier)
bare-reverse-http1 dotnet-httpclient Thin C# H1 reverse (BareHttp1ReverseProxy) — .NET runtime / loopback ceiling for a three-process reverse hop; not a product peer
nginx-reverse-http1 / yarp-reverse-http1 / twp-reverse-http1 dotnet-httpclient Product peers (medals among these three only)

Windows (windows-latest)

Arm Generator Sustain Peak % of origin-HttpClient
origin-direct dotnet-httpclient 50,319
(55 MiB / 40.4% CPU)
50,319
(55 MiB / 40.4% CPU)
100.0%
origin-direct-bombardier bombardier 38,565
(56 MiB / 21.8% CPU)
38,565
(56 MiB / 21.8% CPU)
76.6%
bare-reverse-http1 dotnet-httpclient 25,016
(58 MiB / 43.8% CPU)
25,016
(58 MiB / 43.8% CPU)
49.7%
nginx-reverse-http1 dotnet-httpclient 13,405
(125 MiB / 24.8% CPU)
13,405
(125 MiB / 24.8% CPU)
26.6%
yarp-reverse-http1 dotnet-httpclient 20,802
(87 MiB / 49.0% CPU)
20,802
(87 MiB / 49.0% CPU)
41.3%
twp-reverse-http1 dotnet-httpclient 🥇 24,558
(75 MiB / 48.0% CPU)
24,558
(75 MiB / 48.0% CPU)
48.8%

Linux (ubuntu-latest)

Arm Generator Sustain Peak % of origin-HttpClient
origin-direct dotnet-httpclient 102,038
(80 MiB / 44.2% CPU)
102,038
(80 MiB / 44.2% CPU)
100.0%
origin-direct-bombardier bombardier 61,434
(80 MiB / 37.4% CPU)
61,434
(80 MiB / 37.4% CPU)
60.2%
bare-reverse-http1 dotnet-httpclient 46,442
(70 MiB / 46.0% CPU)
46,442
(70 MiB / 46.0% CPU)
45.5%
nginx-reverse-http1 dotnet-httpclient 🥇 56,585
(76 MiB / 40.3% CPU)
56,585
(76 MiB / 40.3% CPU)
55.5%
yarp-reverse-http1 dotnet-httpclient 41,835
(116 MiB / 49.3% CPU)
41,835
(116 MiB / 49.3% CPU)
41.0%
twp-reverse-http1 dotnet-httpclient 47,721
(95 MiB / 50.9% CPU)
47,721
(95 MiB / 50.9% CPU)
46.8%

Reverse peers are about 50–46% of the origin-direct HttpClient peak on this runner class (Win TWP 50.0%, Lin TWP 45.6%). Prefer the % column over absolute RPS across runs. Bare and origin-direct are controls (not medal peers).

Block B — H2 TLS→H1

Peer ratios (÷YARP / ÷nginx) on median peak; RPS cells embed (MiB / CPU%).

Windows (windows-latest)

Arm Generator Sustain Peak ÷YARP ÷nginx
nginx-reverse-http2 dotnet-httpclient 7,992
(141 MiB / 24.6% CPU)
7,992
(141 MiB / 24.6% CPU)
0.28× 1.00×
yarp-reverse-http2 dotnet-httpclient 28,294
(97 MiB / 54.9% CPU)
28,294
(97 MiB / 54.9% CPU)
1.00× 3.54×
twp-reverse-http2-cleartext dotnet-httpclient 🥇 33,720
(105 MiB / 52.2% CPU)
33,720
(105 MiB / 52.2% CPU)
1.19× 4.22×

Linux (ubuntu-latest)

Arm Generator Sustain Peak ÷YARP ÷nginx
nginx-reverse-http2 dotnet-httpclient 23,276
(102 MiB / 18.9% CPU)
23,276
(102 MiB / 18.9% CPU)
0.53× 1.00×
yarp-reverse-http2 dotnet-httpclient 44,299
(122 MiB / 48.0% CPU)
44,299
(122 MiB / 48.0% CPU)
1.00× 1.90×
twp-reverse-http2-cleartext dotnet-httpclient 🥇 49,167
(124 MiB / 52.1% CPU)
49,167
(124 MiB / 52.1% CPU)
1.11× 2.11×

Block C — H3→H1

Same layout as Block B. Requires QuicListener. nginx needs http_v3_module (Windows nginx has no QUIC). HAProxy needs USE_QUIC (GHA Linux/macOS require it). Envoy 1.20+ includes HTTP/3.

Windows (windows-latest)

Arm Generator Sustain Peak ÷YARP ÷nginx
nginx-reverse-http3-cleartext dotnet-httpclient Not possible (no QUIC) Not possible (no QUIC)
yarp-reverse-http3-cleartext dotnet-httpclient 14,041
(142 MiB / 51.8% CPU)
14,041
(142 MiB / 51.8% CPU)
1.00×
twp-reverse-http3-cleartext dotnet-httpclient 🥇 14,348
(104 MiB / 43.8% CPU)
14,348
(104 MiB / 43.8% CPU)
1.02×

Linux (ubuntu-latest)

Arm Generator Sustain Peak ÷YARP ÷nginx
nginx-reverse-http3-cleartext dotnet-httpclient 0
(110 MiB / 21.8% CPU)
24,928
(110 MiB / 21.8% CPU)
0.89× 1.00×
yarp-reverse-http3-cleartext dotnet-httpclient 27,936
(195 MiB / 48.8% CPU)
27,936
(195 MiB / 48.8% CPU)
1.00× 1.12×
twp-reverse-http3-cleartext dotnet-httpclient 🥇 30,636
(159 MiB / 52.7% CPU)
30,636
(159 MiB / 52.7% CPU)
1.10× 1.23×

Windows — Titanium vs nginx vs HAProxy vs Envoy vs YARP

Client / origin: HTTP version and whether TLS is used (plain = cleartext, TLS = encrypted, QUIC = HTTP/3).

Reverse

Median of 3 repeats on windows-latest (4 vCPU / 16 GiB). Bare reverse 5×5 @ 9a2b3a1ecompare-product 34441526151. Warmup 2s / measure 8s; concurrency 8, 16, 32, 64. Prefer TWP÷peer ratios over absolute RPS. RPS cells include median RSS / CPU at the peak-RPS step as <br><sub>(MiB / CPU%)</sub>. nginx terminate peers use keepalive 256 + streaming buffers. HAProxy / Envoy are Linux-only peers (no official Windows port). Laptop High-perf / cool-paired numbers stay on the local lab. Product 5×5 is ~56-byte JSON keep-alive GET; H2/H3 same-protocol cells are mostly header work with a tiny body (Titanium best case) — see Why this comparison is fair.

Load generators: Reverse inbound H3 arms use dotnet-httpclient (http_version=3.0, RequestVersionExact). nginx/Windows is same-OS only (no QUIC). HAProxy/Envoy are Linux-only terminate peers.

Windows reverse

Client Origin TWP sustain TWP peak nginx sustain nginx peak HAProxy sustain HAProxy peak Envoy sustain Envoy peak YARP sustain YARP peak
HTTP/1 · plain HTTP/1 · plain 🥇 23134
(75 MiB / 47.5% CPU)
🥇 23134
(75 MiB / 47.5% CPU)
13916
(125 MiB / 24.9% CPU)
13916
(125 MiB / 24.9% CPU)
Not possible Not possible Not possible Not possible 21699
(86 MiB / 48.8% CPU)
21699
(86 MiB / 48.8% CPU)
HTTP/1 · plain HTTP/1 · TLS 🥇 20749
(89 MiB / 52.8% CPU)
🥇 20749
(89 MiB / 52.8% CPU)
8366
(135 MiB / 24.6% CPU)
8366
(135 MiB / 24.6% CPU)
Not possible Not possible Not possible Not possible 18784
(100 MiB / 49% CPU)
18784
(100 MiB / 49% CPU)
HTTP/1 · plain HTTP/2 · plain 🥇 45733
(115 MiB / 50.5% CPU)
🥇 45733
(115 MiB / 50.5% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) Not possible Not possible Not possible Not possible 39820
(90 MiB / 49.2% CPU)
39820
(90 MiB / 49.2% CPU)
HTTP/1 · plain HTTP/2 · TLS 🥇 32162
(120 MiB / 46.7% CPU)
🥇 32162
(120 MiB / 46.7% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) Not possible Not possible Not possible Not possible 29670
(98 MiB / 49.7% CPU)
29670
(98 MiB / 49.7% CPU)
HTTP/1 · plain HTTP/3 · QUIC 🥇 18315
(106 MiB / 50.6% CPU)
🥇 18315
(106 MiB / 50.6% CPU)
Not possible (no H3 upstream) Not possible (no H3 upstream) Not possible Not possible Not possible Not possible 17823
(117 MiB / 51% CPU)
17823
(117 MiB / 51% CPU)
HTTP/1 · TLS HTTP/1 · plain 🥇 25720
(90 MiB / 48.4% CPU)
🥇 25720
(90 MiB / 48.4% CPU)
12987
(141 MiB / 24.8% CPU)
12987
(141 MiB / 24.8% CPU)
Not possible Not possible Not possible Not possible 22690
(102 MiB / 48.2% CPU)
22690
(102 MiB / 48.2% CPU)
HTTP/1 · TLS HTTP/1 · TLS 🥇 18942
(91 MiB / 48.6% CPU)
🥇 18942
(91 MiB / 48.6% CPU)
7218
(143 MiB / 24.8% CPU)
7218
(143 MiB / 24.8% CPU)
Not possible Not possible Not possible Not possible 17296
(104 MiB / 49.7% CPU)
17296
(104 MiB / 49.7% CPU)
HTTP/1 · TLS HTTP/2 · plain 🥇 27614
(111 MiB / 44.5% CPU)
🥇 27614
(111 MiB / 44.5% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) Not possible Not possible Not possible Not possible 26015
(104 MiB / 47.6% CPU)
26015
(104 MiB / 47.6% CPU)
HTTP/1 · TLS HTTP/2 · TLS 🥇 32132
(117 MiB / 45.4% CPU)
🥇 32132
(117 MiB / 45.4% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) Not possible Not possible Not possible Not possible 29999
(103 MiB / 48.2% CPU)
29999
(103 MiB / 48.2% CPU)
HTTP/1 · TLS HTTP/3 · QUIC 🥇 16275
(110 MiB / 51.3% CPU)
🥇 16275
(110 MiB / 51.3% CPU)
Not possible (no H3 upstream) Not possible (no H3 upstream) Not possible Not possible Not possible Not possible 15797
(124 MiB / 51.4% CPU)
15797
(124 MiB / 51.4% CPU)
HTTP/2 · plain HTTP/1 · plain 🥇 34933
(89 MiB / 55% CPU)
🥇 34933
(89 MiB / 55% CPU)
9362
(127 MiB / 24.4% CPU)
9362
(127 MiB / 24.4% CPU)
Not possible Not possible Not possible Not possible 31625
(86 MiB / 54.4% CPU)
31625
(86 MiB / 54.4% CPU)
HTTP/2 · plain HTTP/1 · TLS 🥇 35086
(105 MiB / 49% CPU)
🥇 35086
(105 MiB / 49% CPU)
8849
(138 MiB / 24.9% CPU)
8849
(138 MiB / 24.9% CPU)
Not possible Not possible Not possible Not possible 32740
(92 MiB / 50.1% CPU)
32740
(92 MiB / 50.1% CPU)
HTTP/2 · plain HTTP/2 · plain 🥇 112638
(61 MiB / 28.3% CPU)
🥇 112638
(61 MiB / 28.3% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) Not possible Not possible Not possible Not possible 64290
(90 MiB / 49.6% CPU)
64290
(90 MiB / 49.6% CPU)
HTTP/2 · plain HTTP/2 · TLS 🥇 70105
(62 MiB / 20.1% CPU)
🥇 70105
(62 MiB / 20.1% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) Not possible Not possible Not possible Not possible 43971
(99 MiB / 35.9% CPU)
43971
(99 MiB / 35.9% CPU)
HTTP/2 · plain HTTP/3 · QUIC 🥇 33088
(128 MiB / 53.1% CPU)
🥇 33088
(128 MiB / 53.1% CPU)
Not possible (no H3 upstream) Not possible (no H3 upstream) Not possible Not possible Not possible Not possible 31406
(130 MiB / 52% CPU)
31406
(130 MiB / 52% CPU)
HTTP/2 · TLS HTTP/1 · plain 🥇 34943
(97 MiB / 52.2% CPU)
🥇 34943
(97 MiB / 52.2% CPU)
8430
(141 MiB / 24.8% CPU)
8430
(141 MiB / 24.8% CPU)
Not possible Not possible Not possible Not possible 29441
(96 MiB / 53.8% CPU)
29441
(96 MiB / 53.8% CPU)
HTTP/2 · TLS HTTP/1 · TLS 🥇 29487
(97 MiB / 53.6% CPU)
🥇 29487
(97 MiB / 53.6% CPU)
6542
(144 MiB / 24.6% CPU)
6542
(144 MiB / 24.6% CPU)
Not possible Not possible Not possible Not possible 25117
(98 MiB / 54.2% CPU)
25117
(98 MiB / 54.2% CPU)
HTTP/2 · TLS HTTP/2 · plain 🥇 107152
(75 MiB / 29.1% CPU)
🥇 107152
(75 MiB / 29.1% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) Not possible Not possible Not possible Not possible 59098
(102 MiB / 52.7% CPU)
59098
(102 MiB / 52.7% CPU)
HTTP/2 · TLS HTTP/2 · TLS 🥇 84487
(73 MiB / 28.8% CPU)
🥇 84487
(73 MiB / 28.8% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) Not possible Not possible Not possible Not possible 49546
(98 MiB / 49% CPU)
49546
(98 MiB / 49% CPU)
HTTP/2 · TLS HTTP/3 · QUIC 🥇 30034
(127 MiB / 53.4% CPU)
🥇 30034
(127 MiB / 53.4% CPU)
Not possible (no H3 upstream) Not possible (no H3 upstream) Not possible Not possible Not possible Not possible 25937
(123 MiB / 51.5% CPU)
25937
(123 MiB / 51.5% CPU)
HTTP/3 · QUIC HTTP/1 · plain 🥇 19348
(107 MiB / 44% CPU)
🥇 19348
(107 MiB / 44% CPU)
Not measured Not measured Not possible Not possible Not possible Not possible 18041
(143 MiB / 50.9% CPU)
18041
(143 MiB / 50.9% CPU)
HTTP/3 · QUIC HTTP/1 · TLS 🥇 13646
(113 MiB / 46.7% CPU)
🥇 13646
(113 MiB / 46.7% CPU)
Not measured Not measured Not possible Not possible Not possible Not possible 13437
(145 MiB / 52.4% CPU)
13437
(145 MiB / 52.4% CPU)
HTTP/3 · QUIC HTTP/2 · plain 🥇 34128
(136 MiB / 47.6% CPU)
🥇 34128
(136 MiB / 47.6% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) Not possible Not possible Not possible Not possible 25450
(166 MiB / 50.1% CPU)
25450
(166 MiB / 50.1% CPU)
HTTP/3 · QUIC HTTP/2 · TLS 🥇 33850
(138 MiB / 48% CPU)
🥇 33850
(138 MiB / 48% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) Not possible Not possible Not possible Not possible 26828
(168 MiB / 48.5% CPU)
26828
(168 MiB / 48.5% CPU)
HTTP/3 · QUIC HTTP/3 · QUIC 🥇 23150
(121 MiB / 41.8% CPU)
🥇 23150
(121 MiB / 41.8% CPU)
Not possible (no H3 upstream) Not possible (no H3 upstream) Not possible Not possible Not possible Not possible 12064
(167 MiB / 53.1% CPU)
12064
(167 MiB / 53.1% CPU)

MITM (TWP only)

Same Client×Origin wires with interception on (compare-product 34441526151). Lite = no-op handlers (unchanged-lite finish). Full = append-only header mutation (harness: one probe header each way; product: generic append-only relay via MitmCompressedRelayHelper). nginx/HAProxy/Envoy/YARP cannot MITM. Lite÷Reverse / Full÷Reverse vs bare reverse (same job / comparison-group shard). Completion gate: Lite ≥ 0.50× and Full ≥ 0.50× reverse sustain @ c=64 (median of 3 GHA runs); reverse TWP÷YARP ≥ 0.70× (no terminate-peer gate).

v1 append-only relay (2026-08-27): Pre-fix H2→H2 Full÷Reverse was 0.13–0.16× (32960766249). Post-fix @ df172718: H2 plain→H2 plain Full 0.77–0.79×, H3→H1 Full 0.91–0.93×, all MITM arms ≥ 0.70× on median of 33041445371, 33055267086, 33055272140.

v2 drop-only + non-unique append (2026-08-27): MitmStaticRebuildHelper rebuilds static HPACK/QPACK after 1–4 unique header drops; trailing non-unique appends stay on compressed relay. @ 9a2b3a1e: all MITM arms ≥ 0.70× on GHA median (33087088466, 33087091622, 33105885748 Linux; 33087085235, 33087088466, 33087091622 Windows). H2 plain→H2 plain Full 0.77–0.79× (Win) / 0.78× (Lin).

Client Origin Lite sustain Full sustain Lite÷Reverse Full÷Reverse
HTTP/1 · plain HTTP/1 · plain 25054
(82 MiB / 50.4% CPU)
24740
(82 MiB / 51.6% CPU)
1.08× 1.07×
HTTP/1 · plain HTTP/1 · TLS 20351
(95 MiB / 54.2% CPU)
19992
(95 MiB / 52% CPU)
0.98× 0.96×
HTTP/1 · plain HTTP/2 · plain 45468
(110 MiB / 51.5% CPU)
43600
(120 MiB / 49.4% CPU)
0.99× 0.95×
HTTP/1 · plain HTTP/2 · TLS 32619
(118 MiB / 46.8% CPU)
31475
(125 MiB / 46.3% CPU)
1.01× 0.98×
HTTP/1 · plain HTTP/3 · QUIC 17858
(105 MiB / 47.7% CPU)
17488
(104 MiB / 52.6% CPU)
0.98× 0.95×
HTTP/1 · TLS HTTP/1 · plain 24388
(98 MiB / 47.9% CPU)
24773
(95 MiB / 48.2% CPU)
0.95× 0.96×
HTTP/1 · TLS HTTP/1 · TLS 18766
(94 MiB / 49.4% CPU)
18334
(96 MiB / 49.4% CPU)
0.99× 0.97×
HTTP/1 · TLS HTTP/2 · plain 27503
(112 MiB / 47.3% CPU)
27245
(112 MiB / 46.1% CPU)
0.99×
HTTP/1 · TLS HTTP/2 · TLS 31677
(118 MiB / 47.9% CPU)
30700
(117 MiB / 44.2% CPU)
0.99× 0.96×
HTTP/1 · TLS HTTP/3 · QUIC 15862
(113 MiB / 50.9% CPU)
15726
(112 MiB / 50.8% CPU)
0.97× 0.97×
HTTP/2 · plain HTTP/1 · plain 34123
(95 MiB / 55.4% CPU)
33304
(96 MiB / 56.8% CPU)
0.98× 0.95×
HTTP/2 · plain HTTP/1 · TLS 34643
(106 MiB / 50.5% CPU)
34092
(109 MiB / 52.9% CPU)
0.99× 0.97×
HTTP/2 · plain HTTP/2 · plain 86231
(71 MiB / 41.3% CPU)
80246
(73 MiB / 41.9% CPU)
0.77× 0.71×
HTTP/2 · plain HTTP/2 · TLS 72044
(77 MiB / 36.5% CPU)
67973
(77 MiB / 39.7% CPU)
1.03× 0.97×
HTTP/2 · plain HTTP/3 · QUIC 33179
(124 MiB / 53.4% CPU)
32949
(129 MiB / 53.1% CPU)
HTTP/2 · TLS HTTP/1 · plain 33820
(98 MiB / 55.2% CPU)
32652
(107 MiB / 54.9% CPU)
0.97× 0.93×
HTTP/2 · TLS HTTP/1 · TLS 28427
(100 MiB / 56.2% CPU)
27770
(105 MiB / 53.2% CPU)
0.96× 0.94×
HTTP/2 · TLS HTTP/2 · plain 84248
(86 MiB / 40.5% CPU)
80554
(84 MiB / 39.7% CPU)
0.79× 0.75×
HTTP/2 · TLS HTTP/2 · TLS 68743
(86 MiB / 38.1% CPU)
65184
(81 MiB / 39.6% CPU)
0.81× 0.77×
HTTP/2 · TLS HTTP/3 · QUIC 29843
(126 MiB / 54.4% CPU)
29276
(133 MiB / 53.5% CPU)
0.99× 0.97×
HTTP/3 · QUIC HTTP/1 · plain 18648
(117 MiB / 44.9% CPU)
17458
(114 MiB / 44.7% CPU)
0.96× 0.9×
HTTP/3 · QUIC HTTP/1 · TLS 12964
(123 MiB / 46.8% CPU)
12392
(116 MiB / 47.5% CPU)
0.95× 0.91×
HTTP/3 · QUIC HTTP/2 · plain 30904
(132 MiB / 48.6% CPU)
29726
(133 MiB / 50.6% CPU)
0.91× 0.87×
HTTP/3 · QUIC HTTP/2 · TLS 31489
(143 MiB / 48.5% CPU)
30510
(143 MiB / 48.3% CPU)
0.93× 0.9×
HTTP/3 · QUIC HTTP/3 · QUIC 16061
(120 MiB / 49.2% CPU)
15312
(119 MiB / 49.5% CPU)
0.69× 0.66×

Linux — Titanium vs nginx vs HAProxy vs Envoy vs YARP

Reverse

Median of 3 repeats on ubuntu-latest (4 vCPU / 16 GiB). Bare reverse 5×5 @ 9a2b3a1ecompare-product 34441526151. Warmup 2s / measure 8s; concurrency 8, 16, 32, 64. Linux nginx is the authoritative nginx baseline. HAProxy (3.2 USE_QUIC) and Envoy (GitHub release, HTTP/3 compiled in) run on the same loopback shape as nginx/YARP. nginx terminate peers use keepalive 256 + streaming buffers. The RPS workflow installs nginx.org mainline (http_v3_module), a QUIC-enabled HAProxy, Envoy, and libmsquic. Prefer ratios over absolute RPS. Product 5×5 is ~56-byte JSON keep-alive GET; H2/H3 same-protocol cells are mostly header work with a tiny body (Titanium best case) — see Why this comparison is fair.

Linux reverse

Client Origin TWP sustain TWP peak nginx sustain nginx peak HAProxy sustain HAProxy peak Envoy sustain Envoy peak YARP sustain YARP peak
HTTP/1 · plain HTTP/1 · plain 36672
(94 MiB / 50.5% CPU)
36672
(94 MiB / 50.5% CPU)
🥇 44112
(76 MiB / 40.4% CPU)
🥇 44112
(76 MiB / 40.4% CPU)
41748
(67 MiB / 41.3% CPU)
41748
(67 MiB / 41.3% CPU)
24415
(116 MiB / 59.5% CPU)
24415
(116 MiB / 59.5% CPU)
32393
(115 MiB / 48.8% CPU)
32393
(115 MiB / 48.8% CPU)
HTTP/1 · plain HTTP/1 · TLS 28506
(107 MiB / 49.3% CPU)
28506
(107 MiB / 49.3% CPU)
🥇 34687
(93 MiB / 40.7% CPU)
🥇 34687
(93 MiB / 40.7% CPU)
32839
(71 MiB / 43% CPU)
32839
(71 MiB / 43% CPU)
22383
(117 MiB / 56.4% CPU)
22383
(117 MiB / 56.4% CPU)
25710
(138 MiB / 49.6% CPU)
25710
(138 MiB / 49.6% CPU)
HTTP/1 · plain HTTP/2 · plain 🥇 45673
(129 MiB / 52.7% CPU)
🥇 45673
(129 MiB / 52.7% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) 26830
(68 MiB / 42.8% CPU)
26830
(68 MiB / 42.8% CPU)
27447
(116 MiB / 61% CPU)
27447
(116 MiB / 61% CPU)
40965
(125 MiB / 49.4% CPU)
40965
(125 MiB / 49.4% CPU)
HTTP/1 · plain HTTP/2 · TLS 🥇 37934
(147 MiB / 49.1% CPU)
🥇 37934
(147 MiB / 49.1% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) 35699
(68 MiB / 43% CPU)
35699
(68 MiB / 43% CPU)
19949
(117 MiB / 61.9% CPU)
19949
(117 MiB / 61.9% CPU)
35520
(132 MiB / 47.3% CPU)
35520
(132 MiB / 47.3% CPU)
HTTP/1 · plain HTTP/3 · QUIC 🥇 26151
(141 MiB / 53.8% CPU)
🥇 26151
(141 MiB / 53.8% CPU)
Not possible (no H3 upstream) Not possible (no H3 upstream) Not measured Not measured 12126
(120 MiB / 56.3% CPU)
12126
(120 MiB / 56.3% CPU)
24086
(155 MiB / 48.3% CPU)
24086
(155 MiB / 48.3% CPU)
HTTP/1 · TLS HTTP/1 · plain 27742
(111 MiB / 48.9% CPU)
27742
(111 MiB / 48.9% CPU)
33232
(100 MiB / 41.5% CPU)
33232
(100 MiB / 41.5% CPU)
🥇 33283
(85 MiB / 43.6% CPU)
🥇 33283
(85 MiB / 43.6% CPU)
21660
(127 MiB / 56.4% CPU)
21660
(127 MiB / 56.4% CPU)
24735
(142 MiB / 49.4% CPU)
24735
(142 MiB / 49.4% CPU)
HTTP/1 · TLS HTTP/1 · TLS 23878
(111 MiB / 48.2% CPU)
23878
(111 MiB / 48.2% CPU)
🥇 28042
(103 MiB / 41.6% CPU)
🥇 28042
(103 MiB / 41.6% CPU)
27394
(86 MiB / 43.8% CPU)
27394
(86 MiB / 43.8% CPU)
19309
(128 MiB / 55% CPU)
19309
(128 MiB / 55% CPU)
21716
(142 MiB / 49.4% CPU)
21716
(142 MiB / 49.4% CPU)
HTTP/1 · TLS HTTP/2 · plain 🥇 34010
(140 MiB / 51.4% CPU)
🥇 34010
(140 MiB / 51.4% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) 21760
(83 MiB / 42.9% CPU)
21760
(83 MiB / 42.9% CPU)
18208
(127 MiB / 58.6% CPU)
18208
(127 MiB / 58.6% CPU)
30979
(141 MiB / 49.2% CPU)
30979
(141 MiB / 49.2% CPU)
HTTP/1 · TLS HTTP/2 · TLS 🥇 29656
(157 MiB / 48.6% CPU)
🥇 29656
(157 MiB / 48.6% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) 29078
(83 MiB / 44% CPU)
29078
(83 MiB / 44% CPU)
21903
(126 MiB / 56.9% CPU)
21903
(126 MiB / 56.9% CPU)
27210
(146 MiB / 48.3% CPU)
27210
(146 MiB / 48.3% CPU)
HTTP/1 · TLS HTTP/3 · QUIC 🥇 22269
(152 MiB / 52.9% CPU)
🥇 22269
(152 MiB / 52.9% CPU)
Not possible (no H3 upstream) Not possible (no H3 upstream) Not measured Not measured 11093
(130 MiB / 55.9% CPU)
11093
(130 MiB / 55.9% CPU)
19851
(166 MiB / 49.4% CPU)
19851
(166 MiB / 49.4% CPU)
HTTP/2 · plain HTTP/1 · plain 🥇 41263
(126 MiB / 53.1% CPU)
🥇 41263
(126 MiB / 53.1% CPU)
18170
(79 MiB / 19.6% CPU)
18170
(79 MiB / 19.6% CPU)
27652
(69 MiB / 24.4% CPU)
27652
(69 MiB / 24.4% CPU)
17979
(118 MiB / 23% CPU)
17979
(118 MiB / 23% CPU)
39219
(115 MiB / 48.3% CPU)
39219
(115 MiB / 48.3% CPU)
HTTP/2 · plain HTTP/1 · TLS 🥇 32750
(131 MiB / 51% CPU)
🥇 32750
(131 MiB / 51% CPU)
15078
(100 MiB / 19.2% CPU)
15078
(100 MiB / 19.2% CPU)
22285
(71 MiB / 24.5% CPU)
22285
(71 MiB / 24.5% CPU)
16529
(119 MiB / 23.1% CPU)
16529
(119 MiB / 23.1% CPU)
31159
(125 MiB / 48.4% CPU)
31159
(125 MiB / 48.4% CPU)
HTTP/2 · plain HTTP/2 · plain 🥇 97239
(90 MiB / 38% CPU)
🥇 97239
(90 MiB / 38% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) 30261
(69 MiB / 24.3% CPU)
30261
(69 MiB / 24.3% CPU)
24868
(116 MiB / 21.8% CPU)
24868
(116 MiB / 21.8% CPU)
55752
(122 MiB / 47.1% CPU)
55752
(122 MiB / 47.1% CPU)
HTTP/2 · plain HTTP/2 · TLS 🥇 67702
(93 MiB / 38.2% CPU)
🥇 67702
(93 MiB / 38.2% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) 23815
(68 MiB / 24.4% CPU)
23815
(68 MiB / 24.4% CPU)
16231
(118 MiB / 21.5% CPU)
16231
(118 MiB / 21.5% CPU)
44692
(129 MiB / 45.3% CPU)
44692
(129 MiB / 45.3% CPU)
HTTP/2 · plain HTTP/3 · QUIC 🥇 30188
(150 MiB / 51.4% CPU)
🥇 30188
(150 MiB / 51.4% CPU)
Not possible (no H3 upstream) Not possible (no H3 upstream) Not measured Not measured 5340
(121 MiB / 24.8% CPU)
5340
(121 MiB / 24.8% CPU)
28445
(156 MiB / 45.5% CPU)
28445
(156 MiB / 45.5% CPU)
HTTP/2 · TLS HTTP/1 · plain 🥇 38662
(128 MiB / 52.3% CPU)
🥇 38662
(128 MiB / 52.3% CPU)
17745
(100 MiB / 18.8% CPU)
17745
(100 MiB / 18.8% CPU)
24393
(81 MiB / 24.3% CPU)
24393
(81 MiB / 24.3% CPU)
17919
(128 MiB / 22.5% CPU)
17919
(128 MiB / 22.5% CPU)
34084
(122 MiB / 48.1% CPU)
34084
(122 MiB / 48.1% CPU)
HTTP/2 · TLS HTTP/1 · TLS 🥇 30318
(119 MiB / 49.8% CPU)
🥇 30318
(119 MiB / 49.8% CPU)
15083
(110 MiB / 19.6% CPU)
15083
(110 MiB / 19.6% CPU)
20646
(85 MiB / 24.4% CPU)
20646
(85 MiB / 24.4% CPU)
16394
(128 MiB / 22.2% CPU)
16394
(128 MiB / 22.2% CPU)
27788
(131 MiB / 48.5% CPU)
27788
(131 MiB / 48.5% CPU)
HTTP/2 · TLS HTTP/2 · plain 🥇 85544
(102 MiB / 38% CPU)
🥇 85544
(102 MiB / 38% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) 53648
(85 MiB / 24.2% CPU)
53648
(85 MiB / 24.2% CPU)
24277
(126 MiB / 21.5% CPU)
24277
(126 MiB / 21.5% CPU)
44751
(125 MiB / 46.4% CPU)
44751
(125 MiB / 46.4% CPU)
HTTP/2 · TLS HTTP/2 · TLS 🥇 63379
(99 MiB / 36% CPU)
🥇 63379
(99 MiB / 36% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) 22388
(84 MiB / 24.4% CPU)
22388
(84 MiB / 24.4% CPU)
21510
(125 MiB / 20.6% CPU)
21510
(125 MiB / 20.6% CPU)
38643
(128 MiB / 45.3% CPU)
38643
(128 MiB / 45.3% CPU)
HTTP/2 · TLS HTTP/3 · QUIC 🥇 28423
(151 MiB / 50.5% CPU)
🥇 28423
(151 MiB / 50.5% CPU)
Not possible (no H3 upstream) Not possible (no H3 upstream) Not measured Not measured 5476
(129 MiB / 24.6% CPU)
5476
(129 MiB / 24.6% CPU)
25085
(163 MiB / 45.8% CPU)
25085
(163 MiB / 45.8% CPU)
HTTP/3 · QUIC HTTP/1 · plain 23715
(149 MiB / 52.2% CPU)
23715
(149 MiB / 52.2% CPU)
0
(107 MiB / 21.6% CPU)
19206
(107 MiB / 21.6% CPU)
🥇 30835
(86 MiB / 25.2% CPU)
🥇 30835
(86 MiB / 25.2% CPU)
3
(130 MiB / 0.1% CPU)
3
(130 MiB / 0.1% CPU)
21546
(186 MiB / 49% CPU)
21546
(186 MiB / 49% CPU)
HTTP/3 · QUIC HTTP/1 · TLS 🥇 19505
(160 MiB / 49.3% CPU)
🥇 19505
(160 MiB / 49.3% CPU)
0
(117 MiB / 22.7% CPU)
14850
(117 MiB / 22.7% CPU)
Not measured Not measured Not measured Not measured 18423
(197 MiB / 49.9% CPU)
18423
(197 MiB / 49.9% CPU)
HTTP/3 · QUIC HTTP/2 · plain 🥇 31386
(160 MiB / 56.2% CPU)
🥇 31386
(160 MiB / 56.2% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) 29864
(86 MiB / 25.4% CPU)
29864
(86 MiB / 25.4% CPU)
Not measured Not measured 26924
(197 MiB / 48% CPU)
26924
(197 MiB / 48% CPU)
HTTP/3 · QUIC HTTP/2 · TLS 🥇 27669
(154 MiB / 52.3% CPU)
🥇 27669
(154 MiB / 52.3% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) Not measured Not measured Not measured Not measured 24488
(199 MiB / 47.6% CPU)
24488
(199 MiB / 47.6% CPU)
HTTP/3 · QUIC HTTP/3 · QUIC 🥇 21858
(164 MiB / 47.9% CPU)
🥇 21858
(164 MiB / 47.9% CPU)
Not possible (no H3 upstream) Not possible (no H3 upstream) Not measured Not measured Not measured Not measured 17840
(209 MiB / 47% CPU)
17840
(209 MiB / 47% CPU)

MITM (TWP only)

Same Client×Origin wires with interception on (compare-product 34441526151). Lite = no-op handlers (unchanged-lite finish). Full = append-only header mutation (harness: one probe header each way; product: generic append-only relay via MitmCompressedRelayHelper). nginx/HAProxy/Envoy/YARP cannot MITM. Lite÷Reverse / Full÷Reverse vs bare reverse (same job / comparison-group shard). Completion gate: Lite ≥ 0.50× and Full ≥ 0.50× reverse sustain @ c=64 (median of 3 GHA runs); reverse TWP÷YARP ≥ 0.70× (no terminate-peer gate).

v1 append-only relay (2026-08-27): Pre-fix H2→H2 Full÷Reverse was 0.13–0.16× (32960766249). Post-fix @ df172718: H2 plain→H2 plain Full 0.77–0.79×, H3→H1 Full 0.91–0.93×, all MITM arms ≥ 0.70× on median of 33041445371, 33055267086, 33055272140.

v2 drop-only + non-unique append (2026-08-27): MitmStaticRebuildHelper rebuilds static HPACK/QPACK after 1–4 unique header drops; trailing non-unique appends stay on compressed relay. @ 9a2b3a1e: all MITM arms ≥ 0.70× on GHA median (33087088466, 33087091622, 33105885748 Linux; 33087085235, 33087088466, 33087091622 Windows). H2 plain→H2 plain Full 0.77–0.79× (Win) / 0.78× (Lin).

Client Origin Lite sustain Full sustain Lite÷Reverse Full÷Reverse
HTTP/1 · plain HTTP/1 · plain 35578
(88 MiB / 50.3% CPU)
34914
(97 MiB / 50.4% CPU)
0.97× 0.95×
HTTP/1 · plain HTTP/1 · TLS 28326
(114 MiB / 49.8% CPU)
28227
(114 MiB / 49.8% CPU)
0.99× 0.99×
HTTP/1 · plain HTTP/2 · plain 46274
(124 MiB / 54.5% CPU)
44157
(135 MiB / 54.7% CPU)
1.01× 0.97×
HTTP/1 · plain HTTP/2 · TLS 37133
(147 MiB / 51% CPU)
36654
(146 MiB / 51.6% CPU)
0.98× 0.97×
HTTP/1 · plain HTTP/3 · QUIC 26091
(142 MiB / 54.6% CPU)
25394
(145 MiB / 54.4% CPU)
0.97×
HTTP/1 · TLS HTTP/1 · plain 27963
(116 MiB / 50.4% CPU)
27273
(118 MiB / 50% CPU)
1.01× 0.98×
HTTP/1 · TLS HTTP/1 · TLS 24331
(118 MiB / 49% CPU)
23589
(116 MiB / 48.9% CPU)
1.02× 0.99×
HTTP/1 · TLS HTTP/2 · plain 33674
(144 MiB / 52.4% CPU)
32894
(144 MiB / 52% CPU)
0.99× 0.97×
HTTP/1 · TLS HTTP/2 · TLS 29341
(163 MiB / 49.4% CPU)
29024
(160 MiB / 50.3% CPU)
0.99× 0.98×
HTTP/1 · TLS HTTP/3 · QUIC 21874
(159 MiB / 53.2% CPU)
21237
(162 MiB / 53.3% CPU)
0.98× 0.95×
HTTP/2 · plain HTTP/1 · plain 39834
(120 MiB / 54% CPU)
38577
(118 MiB / 53.7% CPU)
0.97× 0.93×
HTTP/2 · plain HTTP/1 · TLS 32663
(135 MiB / 52.2% CPU)
31085
(123 MiB / 51.7% CPU)
0.95×
HTTP/2 · plain HTTP/2 · plain 73656
(93 MiB / 43.9% CPU)
71161
(97 MiB / 42.4% CPU)
0.76× 0.73×
HTTP/2 · plain HTTP/2 · TLS 55089
(105 MiB / 41.2% CPU)
51723
(99 MiB / 40.6% CPU)
0.81× 0.76×
HTTP/2 · plain HTTP/3 · QUIC 30054
(151 MiB / 51.4% CPU)
29788
(156 MiB / 51.7% CPU)
0.99×
HTTP/2 · TLS HTTP/1 · plain 36903
(123 MiB / 53.2% CPU)
35802
(127 MiB / 53.5% CPU)
0.95× 0.93×
HTTP/2 · TLS HTTP/1 · TLS 30528
(130 MiB / 51.2% CPU)
29484
(124 MiB / 50.3% CPU)
1.01× 0.97×
HTTP/2 · TLS HTTP/2 · plain 63418
(114 MiB / 43% CPU)
60875
(111 MiB / 42.8% CPU)
0.74× 0.71×
HTTP/2 · TLS HTTP/2 · TLS 52660
(106 MiB / 40.8% CPU)
49767
(106 MiB / 39.5% CPU)
0.83× 0.79×
HTTP/2 · TLS HTTP/3 · QUIC 28301
(166 MiB / 51.1% CPU)
27450
(154 MiB / 50.7% CPU)
0.97×
HTTP/3 · QUIC HTTP/1 · plain 22951
(150 MiB / 52.3% CPU)
22840
(150 MiB / 52.4% CPU)
0.97× 0.96×
HTTP/3 · QUIC HTTP/1 · TLS 18924
(165 MiB / 50.9% CPU)
18029
(157 MiB / 49.7% CPU)
0.97× 0.92×
HTTP/3 · QUIC HTTP/2 · plain 30229
(167 MiB / 57.6% CPU)
29277
(163 MiB / 56.6% CPU)
0.96× 0.93×
HTTP/3 · QUIC HTTP/2 · TLS 26262
(163 MiB / 53.8% CPU)
25788
(168 MiB / 53.4% CPU)
0.95× 0.93×
HTTP/3 · QUIC HTTP/3 · QUIC 20948
(163 MiB / 50.8% CPU)
20826
(162 MiB / 50.9% CPU)
0.96× 0.95×

macOS — Titanium vs nginx vs HAProxy vs Envoy vs YARP

Reverse

Median of 3 repeats on macos-15-intel (4-core / 14 GB). Bare reverse 5×5 @ 9a2b3a1ecompare-product 34441526151. Warmup 2s / measure 8s; concurrency 8, 16, 32, 64. Prefer TWP÷peer ratios over absolute RPS. RPS cells include median RSS / CPU at the peak-RPS step as <br><sub>(MiB / CPU%)</sub>. The RPS workflow installs Homebrew nginx (http_v3_module), Homebrew HAProxy with USE_QUIC (3.2 source fallback), Envoy (Homebrew bottle or pinned darwin-amd64 1.36.7), Homebrew libmsquic (+ DYLD_*), and YARP. Do not publish from macos-latest (3-core / 7 GB). Product 5×5 is ~56-byte JSON keep-alive GET; H2/H3 same-protocol cells are mostly header work with a tiny body (Titanium best case) — see Why this comparison is fair.

macOS reverse

Client Origin TWP sustain TWP peak nginx sustain nginx peak HAProxy sustain HAProxy peak Envoy sustain Envoy peak YARP sustain YARP peak
HTTP/1 · plain HTTP/1 · plain 🥇 12131
(82 MiB / 32.8% CPU)
🥇 12131
(82 MiB / 32.8% CPU)
6938
(52 MiB / 11.6% CPU)
6938
(52 MiB / 11.6% CPU)
10945
(48 MiB / 23.2% CPU)
10945
(48 MiB / 23.2% CPU)
3332
(72 MiB / 22.4% CPU)
3332
(72 MiB / 22.4% CPU)
10805
(105 MiB / 33.6% CPU)
10805
(105 MiB / 33.6% CPU)
HTTP/1 · plain HTTP/1 · TLS 🥇 11064
(93 MiB / 36.5% CPU)
🥇 11064
(93 MiB / 36.5% CPU)
5152
(73 MiB / 17.4% CPU)
5152
(73 MiB / 17.4% CPU)
7159
(53 MiB / 25.9% CPU)
7159
(53 MiB / 25.9% CPU)
0
(75 MiB / 21% CPU)
2011
(75 MiB / 21% CPU)
9146
(129 MiB / 36.8% CPU)
9146
(129 MiB / 36.8% CPU)
HTTP/1 · plain HTTP/2 · plain 🥇 19185
(88 MiB / 33.8% CPU)
🥇 19185
(88 MiB / 33.8% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) 11853
(50 MiB / 25.6% CPU)
11853
(50 MiB / 25.6% CPU)
6000
(73 MiB / 36.6% CPU)
6000
(73 MiB / 36.6% CPU)
18729
(111 MiB / 34% CPU)
18729
(111 MiB / 34% CPU)
HTTP/1 · plain HTTP/2 · TLS 9927
(129 MiB / 32.9% CPU)
9927
(129 MiB / 32.9% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) 8770
(51 MiB / 26.5% CPU)
8770
(51 MiB / 26.5% CPU)
5948
(73 MiB / 34.9% CPU)
5948
(73 MiB / 34.9% CPU)
🥇 13674
(116 MiB / 32.9% CPU)
🥇 13674
(116 MiB / 32.9% CPU)
HTTP/1 · plain HTTP/3 · QUIC 3662
(90 MiB / 45.3% CPU)
3662
(90 MiB / 45.3% CPU)
Not possible (no H3 upstream) Not possible (no H3 upstream) Not measured Not measured 3393
(75 MiB / 38.2% CPU)
2631
(75 MiB / 38.2% CPU)
🥇 5774
(116 MiB / 33.4% CPU)
🥇 5774
(116 MiB / 33.4% CPU)
HTTP/1 · TLS HTTP/1 · plain 🥇 14162
(94 MiB / 31.5% CPU)
🥇 14162
(94 MiB / 31.5% CPU)
8184
(74 MiB / 18.3% CPU)
8184
(74 MiB / 18.3% CPU)
9938
(64 MiB / 25.6% CPU)
9938
(64 MiB / 25.6% CPU)
4084
(79 MiB / 37.4% CPU)
4328
(79 MiB / 37.4% CPU)
7647
(115 MiB / 32.3% CPU)
7647
(115 MiB / 32.3% CPU)
HTTP/1 · TLS HTTP/1 · TLS 6128
(97 MiB / 31.7% CPU)
6128
(97 MiB / 31.7% CPU)
4903
(81 MiB / 15.5% CPU)
4903
(81 MiB / 15.5% CPU)
🥇 9241
(67 MiB / 28% CPU)
🥇 9241
(67 MiB / 28% CPU)
3594
(80 MiB / 38.9% CPU)
3594
(80 MiB / 38.9% CPU)
6601
(172 MiB / 35% CPU)
6601
(172 MiB / 35% CPU)
HTTP/1 · TLS HTTP/2 · plain 8317
(96 MiB / 32.8% CPU)
8317
(96 MiB / 32.8% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) 🥇 12353
(66 MiB / 28% CPU)
🥇 12353
(66 MiB / 28% CPU)
5378
(80 MiB / 20.9% CPU)
3107
(80 MiB / 20.9% CPU)
10735
(122 MiB / 32.2% CPU)
10735
(122 MiB / 32.2% CPU)
HTTP/1 · TLS HTTP/2 · TLS 8457
(161 MiB / 33.8% CPU)
8457
(161 MiB / 33.8% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) 8558
(65 MiB / 29.3% CPU)
8558
(65 MiB / 29.3% CPU)
4938
(79 MiB / 39.8% CPU)
5195
(79 MiB / 39.8% CPU)
🥇 9023
(120 MiB / 28.7% CPU)
🥇 9023
(120 MiB / 28.7% CPU)
HTTP/1 · TLS HTTP/3 · QUIC 2677
(112 MiB / 44.9% CPU)
2677
(112 MiB / 44.9% CPU)
Not possible (no H3 upstream) Not possible (no H3 upstream) Not measured Not measured 🥇 4392
(81 MiB / 37.8% CPU)
🥇 2176
(81 MiB / 37.8% CPU)
3589
(152 MiB / 31.7% CPU)
3589
(152 MiB / 31.7% CPU)
HTTP/2 · plain HTTP/1 · plain 12398
(88 MiB / 35.1% CPU)
12398
(88 MiB / 35.1% CPU)
10718
(58 MiB / 15.4% CPU)
10718
(58 MiB / 15.4% CPU)
7841
(54 MiB / 18% CPU)
7841
(54 MiB / 18% CPU)
3391
(74 MiB / 20.7% CPU)
3391
(74 MiB / 20.7% CPU)
🥇 12934
(105 MiB / 37.8% CPU)
🥇 12934
(105 MiB / 37.8% CPU)
HTTP/2 · plain HTTP/1 · TLS 13814
(94 MiB / 38.6% CPU)
13814
(94 MiB / 38.6% CPU)
12186
(85 MiB / 16% CPU)
12186
(85 MiB / 16% CPU)
6688
(56 MiB / 18.9% CPU)
6688
(56 MiB / 18.9% CPU)
5045
(77 MiB / 21.3% CPU)
5045
(77 MiB / 21.3% CPU)
🥇 14337
(121 MiB / 42.3% CPU)
🥇 14337
(121 MiB / 42.3% CPU)
HTTP/2 · plain HTTP/2 · plain 🥇 30992
(73 MiB / 25.8% CPU)
🥇 30992
(73 MiB / 25.8% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) 8615
(54 MiB / 17.5% CPU)
8615
(54 MiB / 17.5% CPU)
5442
(72 MiB / 20% CPU)
5442
(72 MiB / 20% CPU)
22898
(109 MiB / 37.5% CPU)
22898
(109 MiB / 37.5% CPU)
HTTP/2 · plain HTTP/2 · TLS 🥇 24573
(77 MiB / 27.7% CPU)
🥇 24573
(77 MiB / 27.7% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) 11876
(58 MiB / 19% CPU)
11876
(58 MiB / 19% CPU)
6393
(73 MiB / 20.2% CPU)
6393
(73 MiB / 20.2% CPU)
18700
(116 MiB / 34.6% CPU)
18700
(116 MiB / 34.6% CPU)
HTTP/2 · plain HTTP/3 · QUIC 4840
(97 MiB / 49.3% CPU)
4840
(97 MiB / 49.3% CPU)
Not possible (no H3 upstream) Not possible (no H3 upstream) Not measured Not measured 3760
(74 MiB / 22.4% CPU)
3760
(74 MiB / 22.4% CPU)
🥇 8092
(117 MiB / 33.9% CPU)
🥇 8092
(117 MiB / 33.9% CPU)
HTTP/2 · TLS HTTP/1 · plain 🥇 13829
(94 MiB / 39.2% CPU)
🥇 13829
(94 MiB / 39.2% CPU)
9070
(73 MiB / 14.5% CPU)
9070
(73 MiB / 14.5% CPU)
5237
(66 MiB / 16.1% CPU)
5237
(66 MiB / 16.1% CPU)
3516
(81 MiB / 20.4% CPU)
3516
(81 MiB / 20.4% CPU)
13572
(113 MiB / 37.3% CPU)
13572
(113 MiB / 37.3% CPU)
HTTP/2 · TLS HTTP/1 · TLS 🥇 9182
(96 MiB / 37.3% CPU)
🥇 9182
(96 MiB / 37.3% CPU)
6812
(90 MiB / 15.3% CPU)
6812
(90 MiB / 15.3% CPU)
4920
(66 MiB / 18.2% CPU)
4920
(66 MiB / 18.2% CPU)
2505
(83 MiB / 20.1% CPU)
2505
(83 MiB / 20.1% CPU)
9080
(124 MiB / 40.6% CPU)
9080
(124 MiB / 40.6% CPU)
HTTP/2 · TLS HTTP/2 · plain 🥇 47325
(81 MiB / 29% CPU)
🥇 47325
(81 MiB / 29% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) 5750
(67 MiB / 5.9% CPU)
2851
(67 MiB / 5.9% CPU)
4704
(79 MiB / 19% CPU)
4704
(79 MiB / 19% CPU)
22095
(115 MiB / 37.6% CPU)
22095
(115 MiB / 37.6% CPU)
HTTP/2 · TLS HTTP/2 · TLS 🥇 29038
(83 MiB / 27.1% CPU)
🥇 29038
(83 MiB / 27.1% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) 6022
(67 MiB / 18.3% CPU)
6022
(67 MiB / 18.3% CPU)
4494
(79 MiB / 18.6% CPU)
4494
(79 MiB / 18.6% CPU)
16458
(118 MiB / 35% CPU)
16458
(118 MiB / 35% CPU)
HTTP/2 · TLS HTTP/3 · QUIC 4226
(108 MiB / 36% CPU)
4226
(108 MiB / 36% CPU)
Not possible (no H3 upstream) Not possible (no H3 upstream) Not measured Not measured 1772
(81 MiB / 21.6% CPU)
1772
(81 MiB / 21.6% CPU)
🥇 4805
(125 MiB / 33.7% CPU)
🥇 4805
(125 MiB / 33.7% CPU)
HTTP/3 · QUIC HTTP/1 · plain 5834
(101 MiB / 39.5% CPU)
5834
(101 MiB / 39.5% CPU)
0
(63 MiB / 11.2% CPU)
7464
(63 MiB / 11.2% CPU)
🥇 10727
(66 MiB / 22% CPU)
🥇 10727
(66 MiB / 22% CPU)
1595
(85 MiB / 26.4% CPU)
1595
(85 MiB / 26.4% CPU)
5558
(187 MiB / 35% CPU)
5558
(187 MiB / 35% CPU)
HTTP/3 · QUIC HTTP/1 · TLS 3723
(119 MiB / 38.2% CPU)
3723
(119 MiB / 38.2% CPU)
0
(66 MiB / 11.1% CPU)
4316
(66 MiB / 11.1% CPU)
🥇 5430
(69 MiB / 21.8% CPU)
🥇 5430
(69 MiB / 21.8% CPU)
Not measured Not measured 4786
(197 MiB / 35.5% CPU)
4786
(197 MiB / 35.5% CPU)
HTTP/3 · QUIC HTTP/2 · plain 4576
(97 MiB / 41.3% CPU)
4576
(97 MiB / 41.3% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) 🥇 5954
(66 MiB / 14.4% CPU)
🥇 5954
(66 MiB / 14.4% CPU)
Not measured Not measured 5642
(176 MiB / 34.2% CPU)
5642
(176 MiB / 34.2% CPU)
HTTP/3 · QUIC HTTP/2 · TLS 5532
(106 MiB / 41.4% CPU)
5532
(106 MiB / 41.4% CPU)
Not possible (no H2 upstream) Not possible (no H2 upstream) 6633
(68 MiB / 21.5% CPU)
6633
(68 MiB / 21.5% CPU)
Not measured Not measured 🥇 7854
(167 MiB / 32.5% CPU)
🥇 7854
(167 MiB / 32.5% CPU)
HTTP/3 · QUIC HTTP/3 · QUIC 3460
(96 MiB / 35% CPU)
3460
(96 MiB / 35% CPU)
Not possible (no H3 upstream) Not possible (no H3 upstream) Not measured Not measured Not measured Not measured 🥇 4659
(188 MiB / 34.4% CPU)
🥇 4659
(188 MiB / 34.4% CPU)

MITM (TWP only)

Same Client×Origin wires with interception on (compare-product 34441526151). Lite = no-op handlers (unchanged-lite finish). Full = append-only header mutation (harness: one probe header each way; product: generic append-only relay via MitmCompressedRelayHelper). nginx/HAProxy/Envoy/YARP cannot MITM. Lite÷Reverse / Full÷Reverse vs bare reverse (same job / comparison-group shard). Completion gate: Lite ≥ 0.50× and Full ≥ 0.50× reverse sustain @ c=64 (median of 3 GHA runs); reverse TWP÷YARP ≥ 0.70× (no terminate-peer gate).

v1 append-only relay (2026-08-27): Pre-fix H2→H2 Full÷Reverse was 0.13–0.16× (32960766249). Post-fix @ df172718: H2 plain→H2 plain Full 0.77–0.79×, H3→H1 Full 0.91–0.93×, all MITM arms ≥ 0.70× on median of 33041445371, 33055267086, 33055272140.

v2 drop-only + non-unique append (2026-08-27): MitmStaticRebuildHelper rebuilds static HPACK/QPACK after 1–4 unique header drops; trailing non-unique appends stay on compressed relay. @ 9a2b3a1e: all MITM arms ≥ 0.70× on GHA median (33087088466, 33087091622, 33105885748 Linux; 33087085235, 33087088466, 33087091622 Windows). H2 plain→H2 plain Full 0.77–0.79× (Win) / 0.78× (Lin).

Client Origin Lite sustain Full sustain Lite÷Reverse Full÷Reverse
HTTP/1 · plain HTTP/1 · plain 11715
(84 MiB / 35.6% CPU)
11001
(84 MiB / 31.8% CPU)
0.97× 0.91×
HTTP/1 · plain HTTP/1 · TLS 7193
(94 MiB / 31.1% CPU)
8678
(94 MiB / 35.3% CPU)
0.65× 0.78×
HTTP/1 · plain HTTP/2 · plain 14866
(89 MiB / 36.3% CPU)
13716
(90 MiB / 35.7% CPU)
0.77× 0.71×
HTTP/1 · plain HTTP/2 · TLS 11164
(109 MiB / 33.4% CPU)
9186
(108 MiB / 32.6% CPU)
1.12× 0.93×
HTTP/1 · plain HTTP/3 · QUIC 3459
(91 MiB / 39.6% CPU)
3710
(90 MiB / 40.3% CPU)
0.94× 1.01×
HTTP/1 · TLS HTTP/1 · plain 8052
(95 MiB / 30.3% CPU)
10123
(96 MiB / 33.1% CPU)
0.57× 0.71×
HTTP/1 · TLS HTTP/1 · TLS 6914
(98 MiB / 36% CPU)
9190
(98 MiB / 33.3% CPU)
1.13× 1.5×
HTTP/1 · TLS HTTP/2 · plain 8443
(123 MiB / 35.7% CPU)
8055
(102 MiB / 33.1% CPU)
1.02× 0.97×
HTTP/1 · TLS HTTP/2 · TLS 8738
(133 MiB / 33.2% CPU)
7260
(157 MiB / 32.6% CPU)
1.03× 0.86×
HTTP/1 · TLS HTTP/3 · QUIC 2633
(105 MiB / 42.6% CPU)
2842
(102 MiB / 46.3% CPU)
0.98× 1.06×
HTTP/2 · plain HTTP/1 · plain 13742
(88 MiB / 38.4% CPU)
13895
(90 MiB / 37.5% CPU)
1.11× 1.12×
HTTP/2 · plain HTTP/1 · TLS 14725
(96 MiB / 40.8% CPU)
10701
(96 MiB / 35.5% CPU)
1.07× 0.77×
HTTP/2 · plain HTTP/2 · plain 24126
(76 MiB / 29.9% CPU)
24457
(76 MiB / 29.7% CPU)
0.78× 0.79×
HTTP/2 · plain HTTP/2 · TLS 23664
(83 MiB / 31.7% CPU)
24893
(81 MiB / 31% CPU)
0.96× 1.01×
HTTP/2 · plain HTTP/3 · QUIC 4822
(96 MiB / 45% CPU)
5035
(95 MiB / 45.9% CPU)
1.04×
HTTP/2 · TLS HTTP/1 · plain 13114
(92 MiB / 38.3% CPU)
12954
(91 MiB / 38.1% CPU)
0.95× 0.94×
HTTP/2 · TLS HTTP/1 · TLS 9205
(97 MiB / 36% CPU)
9788
(97 MiB / 39.1% CPU)
1.07×
HTTP/2 · TLS HTTP/2 · plain 28081
(86 MiB / 32% CPU)
24916
(87 MiB / 30.4% CPU)
0.59× 0.53×
HTTP/2 · TLS HTTP/2 · TLS 22874
(87 MiB / 29.6% CPU)
29489
(89 MiB / 32% CPU)
0.79× 1.02×
HTTP/2 · TLS HTTP/3 · QUIC 4679
(105 MiB / 37.9% CPU)
4453
(106 MiB / 39.3% CPU)
1.11× 1.05×
HTTP/3 · QUIC HTTP/1 · plain 4000
(102 MiB / 35% CPU)
4530
(102 MiB / 38.8% CPU)
0.69× 0.78×
HTTP/3 · QUIC HTTP/1 · TLS 3931
(116 MiB / 38.3% CPU)
3992
(115 MiB / 40% CPU)
1.06× 1.07×
HTTP/3 · QUIC HTTP/2 · plain 4272
(98 MiB / 39% CPU)
4718
(98 MiB / 39.8% CPU)
0.93× 1.03×
HTTP/3 · QUIC HTTP/2 · TLS 5183
(106 MiB / 38.5% CPU)
4838
(108 MiB / 38.9% CPU)
0.94× 0.87×
HTTP/3 · QUIC HTTP/3 · QUIC 3211
(94 MiB / 37.3% CPU)
3887
(95 MiB / 37.3% CPU)
0.93× 1.12×

Editions (CLI / Plus / Intercept)

Note: twp-reverse-http1 and other library rows use Core with probe-tuned settings (no logging, no Via header, probe-warmed certs). Edition rows use titanium run -c twp.yaml product defaults — prefer the ÷baseline ratio column over absolute RPS. Inspector GUI is not spawnable in the harness; session-path overhead is twp-cli-intercept-http1 (route RequestHeaderSet transform). Pre-origin Plus middleware (CIDR/WAF/JWT/rate-limit) runs on H1 terminate-lite without SessionEventArgs; JWT caches successful bearer validations. Maintainer gate thresholds live under Maintainer notes.

Median of 3 repeats @ 6d2a7c9d. Source: Actions 33259699099. Warmup 2s / measure 8s; concurrency 8–64; sustain = median peak RPS among SLO-pass steps @ c=64. RPS cells include (MiB / CPU%) at that step.

Arm Win sustain Win peak Linux sustain Linux peak Win÷ Lin÷ Gate
twp-cli-reverse-http1 vs library 32214
(118 MiB / 43.4% CPU)
32219 47734
(151 MiB / 49.0% CPU)
47844 1.02× 1.04× 0.80×
twp-cli-reverse-http1-tls vs library TLS 26495
(138 MiB / 48.3% CPU)
26651 36932
(174 MiB / 48.5% CPU)
37200 1.01× 1.00× 0.80×
twp-cli-reverse-http1-route vs CLI 32394
(120 MiB / 47.7% CPU)
32428 47369
(149 MiB / 49.2% CPU)
47398 1.01× 0.99× 0.90×
twp-cli-plus-base-http1 vs CLI 32475
(123 MiB / 46.0% CPU)
32695 47322
(154 MiB / 49.8% CPU)
47744 1.01× 0.99× 0.90×
twp-cli-plus-cache-http1 (cold) vs CLI 34029
(118 MiB / 64.5% CPU)
34460 49409
(148 MiB / 62.3% CPU)
50104 1.06× 1.04× 0.70×
twp-cli-intercept-http1 vs CLI 25219
(124 MiB / 54.0% CPU)
25377 35969
(155 MiB / 51.2% CPU)
35977 0.78× 0.75× 0.70×
twp-cli-plus-waf-http1 vs CLI 31653
(124 MiB / 46.8% CPU)
31837 46367
(151 MiB / 49.6% CPU)
46685 0.98× 0.97× 0.80×
twp-cli-plus-cidr-http1 vs CLI 31730
(123 MiB / 51.1% CPU)
31757 46828
(150 MiB / 50.2% CPU)
47093 0.98× 0.98× 0.80×
twp-cli-plus-jwt-http1 vs CLI 30326
(138 MiB / 46.6% CPU)
30386 43906
(179 MiB / 49.5% CPU)
44433 0.94× 0.92× 0.70×
twp-cli-plus-ratelimit-http1 vs CLI 31713
(123 MiB / 48.8% CPU)
31944 46435
(151 MiB / 49.4% CPU)
46860 0.98× 0.97× 0.80×
twp-cli-plus-resilience-http1 vs CLI 32373
(128 MiB / 50.5% CPU)
32416 47302
(155 MiB / 49.5% CPU)
47654 1.00× 0.99× 0.85×
twp-cli-plus-discovery-file-http1 vs CLI 32209
(121 MiB / 46.5% CPU)
32332 47485
(151 MiB / 49.1% CPU)
47770 1.00× 0.99× 0.80×
twp-cli-plus-metrics-scrape-http1 vs CLI 32192
(126 MiB / 44.8% CPU)
32427 47348
(159 MiB / 49.5% CPU)
48665 1.00× 0.99× 0.80×
twp-cli-plus-cache-hit-http1 vs cache cold 34015
(117 MiB / 66.0% CPU)
34022 49153
(149 MiB / 63.1% CPU)
49358 1.00× 0.99× 0.90×
twp-cli-static-http1 vs CLI 53078
(109 MiB / 52.1% CPU)
53980 78333
(150 MiB / 48.4% CPU)
82955 1.65× 1.64× 0.85×
twp-cli-logging-http1 vs CLI 32440
(119 MiB / 47.4% CPU)
32581 47624
(150 MiB / 49.3% CPU)
48604 1.01× 1.00× 0.90×
twp-cli-lb-leasttime-http1 vs route 29649
(134 MiB / 54.7% CPU)
30386 44790
(180 MiB / 50.6% CPU)
44825 0.92× 0.95× 0.85×
twp-cli-dialect-twp-http1 vs CLI 32461
(114 MiB / 49.7% CPU)
32780 47898
(145 MiB / 49.3% CPU)
48154 1.01× 1.00× 0.90×

validate-edition-gates.ps1 passed on both OS for this run. Library baselines @ c=64 (same job): Win H1 31561 / TLS 26128; Linux H1 45818 / TLS 36869. Laptop smoke ratios stay on Performance Local Lab — Editions.

Cross-version (7.0 vs 6.0)

Same reverse matrix measured on Titanium 7.0 versus committed 6.0 baselines (33087088466). Median of 3 @ 0ef6d4dd. Source: Actions 33270571908. Sustain RPS @ c=64. Absolute 7.0÷6.0 ≈ 0.96–1.00× on same-protocol arms; peer-normalized ratios ≈ 0.90–1.03×.

Arm Win 6.0 Win 7.0 Win÷ Linux 6.0 Linux 7.0 Lin÷
twp-reverse-http1 32525 32213 0.99× 32755 31932 0.97×
twp-reverse-http1-tls 26461 26570 1.00× 22784 22351 0.98×
twp-reverse-http2 76038 75316 0.99× 47690 46678 0.98×
twp-reverse-http2-cleartext 40347 40236 1.00× 34556 33316 0.96×
twp-reverse-http3 17529 17380 0.99× 19468 19423 1.00×
twp-reverse-http3-cleartext 19956 19529 0.98× 20395 20070 0.98×
yarp-reverse-http1 (peer) 27504 27254 0.99× 27713 27102 0.98×
yarp-reverse-http2 (peer) 35553 35189 0.99× 29111 28733 0.99×

Both OS CSVs passed the cross-version check for this run. MITM arms are measured with the product reverse matrix, not this reverse-only comparison.

Heavier reverse workloads

Same runners and harness as the tiny-GET tables, but with larger bodies, POST, lossy links, TLS cost, and architecture-sensitive paths (slow consumer / early response / duplex). Charts: rps-heavier-*-{windows,linux}.png. PUT with the same body is the same proxy work as POST; DELETE with no body matches GET — only POST is published. Bodies/POST/lossy stay half-duplex. Laptop numbers are on Performance Local Lab. How maintainers refresh these tables (modes, shards, paste scripts) is under Maintainer notes. Larger-body check: 64 / 256 KiB H2 TLS→H2 TLS is where body copy dominates headers — Titanium is behind YARP here (~0.69–0.76× at 64 KiB), unlike the tiny-GET H2↔H2 medals above.

Lossy link = userspace delay/drop shim (not kernel netem): TCP gets per-buffer delay + occasional whole-connection stalls (honest head-of-line for multiplexed HTTP/2); UDP gets per-datagram delay + drops (QUIC). Lossy tables publish HTTP/1, HTTP/2, and HTTP/3.

Windows — heavier reverse GET (64 KiB / 256 KiB)

Windows heavier bodies

Median of 3 repeats on windows-latest @ 9a2b3a1e. Source: Actions 34441570199 (compare-bodies). Warmup 2s / measure 8s. RPS cells include (MiB / CPU%) footprints.

Body Client Origin TWP sustain TWP peak nginx sustain nginx peak HAProxy sustain HAProxy peak Envoy sustain Envoy peak YARP sustain YARP peak
64 KiB HTTP/1 · TLS HTTP/1 · plain 🥇 13,191
(122 MiB / 46.7% CPU)
13,191
(122 MiB / 46.7% CPU)
924
(142 MiB / 24.8% CPU)
924
(142 MiB / 24.8% CPU)
Not possible Not possible Not possible Not possible 11,473
(133 MiB / 47.5% CPU)
11,473
(133 MiB / 47.5% CPU)
64 KiB HTTP/2 · TLS HTTP/1 · plain 🥇 11,769
(173 MiB / 46.2% CPU)
11,769
(173 MiB / 46.2% CPU)
898
(142 MiB / 24.8% CPU)
898
(142 MiB / 24.8% CPU)
Not possible Not possible Not possible Not possible 9,560
(135 MiB / 48.1% CPU)
9,560
(135 MiB / 48.1% CPU)
64 KiB HTTP/3 · QUIC HTTP/1 · plain 🥇 5,958
(139 MiB / 41.5% CPU)
5,958
(139 MiB / 41.5% CPU)
Not possible (no QUIC) Not possible (no QUIC) Not possible Not possible Not possible Not possible 5,060
(185 MiB / 51.0% CPU)
5,060
(185 MiB / 51.0% CPU)
256 KiB HTTP/1 · TLS HTTP/1 · plain 🥇 3,693
(136 MiB / 42.1% CPU)
3,693
(136 MiB / 42.1% CPU)
241
(142 MiB / 24.9% CPU)
241
(142 MiB / 24.9% CPU)
Not possible Not possible Not possible Not possible 3,325
(130 MiB / 47.2% CPU)
3,325
(130 MiB / 47.2% CPU)
256 KiB HTTP/2 · TLS HTTP/1 · plain 🥇 3,784
(149 MiB / 36.2% CPU)
3,784
(149 MiB / 36.2% CPU)
230
(142 MiB / 24.8% CPU)
230
(142 MiB / 24.8% CPU)
Not possible Not possible Not possible Not possible 2,625
(135 MiB / 45.2% CPU)
2,625
(135 MiB / 45.2% CPU)
256 KiB HTTP/3 · QUIC HTTP/1 · plain 🥇 1,535
(111 MiB / 40.4% CPU)
1,535
(111 MiB / 40.4% CPU)
Not possible (no QUIC) Not possible (no QUIC) Not possible Not possible Not possible Not possible 1,385
(169 MiB / 44.6% CPU)
1,385
(169 MiB / 44.6% CPU)
64 KiB HTTP/2 · plain HTTP/1 · plain 🥇 14,010
(174 MiB / 40.5% CPU)
14,010
(174 MiB / 40.5% CPU)
5,865
(127 MiB / 24.0% CPU)
5,865
(127 MiB / 24.0% CPU)
Not possible Not possible Not possible Not possible 12,443
(111 MiB / 39.6% CPU)
12,443
(111 MiB / 39.6% CPU)
64 KiB HTTP/2 · TLS HTTP/2 · plain 6,319
(79 MiB / 38.1% CPU)
6,319
(79 MiB / 38.1% CPU)
Not possible Not possible Not possible Not possible Not possible Not possible 🥇 9,493
(131 MiB / 50.3% CPU)
9,493
(131 MiB / 50.3% CPU)
64 KiB HTTP/2 · TLS HTTP/2 · TLS 5,660
(80 MiB / 36.4% CPU)
5,660
(80 MiB / 36.4% CPU)
Not possible Not possible Not possible Not possible Not possible Not possible 🥇 8,201
(141 MiB / 47.6% CPU)
8,201
(141 MiB / 47.6% CPU)
64 KiB HTTP/3 · QUIC HTTP/2 · TLS 4,657
(129 MiB / 46.1% CPU)
4,657
(129 MiB / 46.1% CPU)
Not possible Not possible Not possible Not possible Not possible Not possible 🥇 5,021
(195 MiB / 47.6% CPU)
5,021
(195 MiB / 47.6% CPU)
64 KiB HTTP/3 · QUIC HTTP/1 · TLS 🥇 6,149
(148 MiB / 42.2% CPU)
6,149
(148 MiB / 42.2% CPU)
Not possible (no QUIC) Not possible (no QUIC) Not possible Not possible Not possible Not possible 4,496
(191 MiB / 49.0% CPU)
4,496
(191 MiB / 49.0% CPU)
256 KiB HTTP/2 · plain HTTP/1 · plain 🥇 4,457
(144 MiB / 31.8% CPU)
4,457
(144 MiB / 31.8% CPU)
1,759
(127 MiB / 23.6% CPU)
1,759
(127 MiB / 23.6% CPU)
Not possible Not possible Not possible Not possible 3,719
(123 MiB / 37.8% CPU)
3,719
(123 MiB / 37.8% CPU)
256 KiB HTTP/2 · TLS HTTP/2 · plain 1,976
(84 MiB / 29.9% CPU)
1,976
(84 MiB / 29.9% CPU)
Not possible Not possible Not possible Not possible Not possible Not possible 🥇 2,325
(169 MiB / 46.5% CPU)
2,325
(169 MiB / 46.5% CPU)
256 KiB HTTP/2 · TLS HTTP/2 · TLS 1,758
(87 MiB / 29.7% CPU)
1,758
(87 MiB / 29.7% CPU)
Not possible Not possible Not possible Not possible Not possible Not possible 🥇 2,109
(153 MiB / 44.9% CPU)
2,109
(153 MiB / 44.9% CPU)
256 KiB HTTP/3 · QUIC HTTP/2 · TLS 1,164
(153 MiB / 43.0% CPU)
1,164
(153 MiB / 43.0% CPU)
Not possible Not possible Not possible Not possible Not possible Not possible 🥇 1,319
(186 MiB / 44.8% CPU)
1,319
(186 MiB / 44.8% CPU)
256 KiB HTTP/3 · QUIC HTTP/1 · TLS 🥇 1,404
(146 MiB / 41.0% CPU)
1,404
(146 MiB / 41.0% CPU)
Not possible (no QUIC) Not possible (no QUIC) Not possible Not possible Not possible Not possible 1,269
(196 MiB / 44.8% CPU)
1,269
(196 MiB / 44.8% CPU)

nginx/Windows collapses on large reverse bodies in this harness; treat as same-OS only. H1 TLS 64 KiB1.11× YARP; 256 KiB1.23×. H2→H1 64 KiB ≈ 1.21×; H3→H1 64 KiB ≈ 1.18×.

Linux — heavier reverse GET (64 KiB / 256 KiB)

Linux heavier bodies

Median of 3 repeats @ 9a2b3a1e. Source: Actions 34441570199 (compare-bodies). Warmup 2s / measure 8s.

Body Client Origin TWP sustain TWP peak nginx sustain nginx peak HAProxy sustain HAProxy peak Envoy sustain Envoy peak YARP sustain YARP peak
64 KiB HTTP/1 · TLS HTTP/1 · plain 8,010
(176 MiB / 45.3% CPU)
8,010
(176 MiB / 45.3% CPU)
5,555
(100 MiB / 52.4% CPU)
5,555
(100 MiB / 52.4% CPU)
🥇 9,012
(84 MiB / 40.6% CPU)
9,012
(84 MiB / 40.6% CPU)
7,524
(131 MiB / 45.8% CPU)
7,524
(131 MiB / 45.8% CPU)
6,504
(169 MiB / 48.4% CPU)
6,504
(169 MiB / 48.4% CPU)
64 KiB HTTP/2 · TLS HTTP/1 · plain 9,850
(231 MiB / 39.4% CPU)
9,850
(231 MiB / 39.4% CPU)
3,314
(103 MiB / 10.9% CPU)
3,314
(103 MiB / 10.9% CPU)
🥇 10,145
(87 MiB / 24.0% CPU)
10,145
(87 MiB / 24.0% CPU)
8,389
(141 MiB / 23.7% CPU)
8,389
(141 MiB / 23.7% CPU)
8,231
(164 MiB / 46.6% CPU)
8,231
(164 MiB / 46.6% CPU)
64 KiB HTTP/3 · QUIC HTTP/1 · plain 🥇 5,646
(184 MiB / 44.2% CPU)
5,646
(184 MiB / 44.2% CPU)
0
(129 MiB / 22.4% CPU)
1,678
(129 MiB / 22.4% CPU)
Not measured Not measured Not measured Not measured 4,421
(231 MiB / 51.5% CPU)
4,421
(231 MiB / 51.5% CPU)
256 KiB HTTP/1 · TLS HTTP/1 · plain 2,766
(128 MiB / 37.7% CPU)
2,766
(128 MiB / 37.7% CPU)
1,735
(100 MiB / 53.6% CPU)
1,735
(100 MiB / 53.6% CPU)
🥇 2,974
(83 MiB / 34.0% CPU)
2,974
(83 MiB / 34.0% CPU)
2,701
(145 MiB / 33.9% CPU)
2,701
(145 MiB / 33.9% CPU)
2,164
(166 MiB / 45.8% CPU)
2,164
(166 MiB / 45.8% CPU)
256 KiB HTTP/2 · TLS HTTP/1 · plain 2,550
(209 MiB / 32.3% CPU)
2,550
(209 MiB / 32.3% CPU)
1,728
(103 MiB / 19.0% CPU)
1,728
(103 MiB / 19.0% CPU)
🥇 3,276
(86 MiB / 19.5% CPU)
3,276
(86 MiB / 19.5% CPU)
3,128
(168 MiB / 20.2% CPU)
3,128
(168 MiB / 20.2% CPU)
2,201
(163 MiB / 43.1% CPU)
2,201
(163 MiB / 43.1% CPU)
256 KiB HTTP/3 · QUIC HTTP/1 · plain 🥇 1,458
(159 MiB / 43.3% CPU)
1,458
(159 MiB / 43.3% CPU)
0
(120 MiB / 20.0% CPU)
24
(120 MiB / 20.0% CPU)
Not measured Not measured Not measured Not measured 1,278
(218 MiB / 48.1% CPU)
1,278
(218 MiB / 48.1% CPU)
64 KiB HTTP/2 · plain HTTP/1 · plain 🥇 13,722
(251 MiB / 41.5% CPU)
13,722
(251 MiB / 41.5% CPU)
4,929
(80 MiB / 10.4% CPU)
4,929
(80 MiB / 10.4% CPU)
13,114
(72 MiB / 23.9% CPU)
13,114
(72 MiB / 23.9% CPU)
11,084
(133 MiB / 23.5% CPU)
11,084
(133 MiB / 23.5% CPU)
13,042
(143 MiB / 45.4% CPU)
13,042
(143 MiB / 45.4% CPU)
64 KiB HTTP/2 · TLS HTTP/2 · plain 3,419
(101 MiB / 40.6% CPU)
3,419
(101 MiB / 40.6% CPU)
Not possible Not possible 0
(83 MiB / 19.9% CPU)
0
(83 MiB / 19.9% CPU)
0
(126 MiB / 22.4% CPU)
0
(126 MiB / 22.4% CPU)
🥇 4,578
(185 MiB / 46.3% CPU)
4,578
(185 MiB / 46.3% CPU)
64 KiB HTTP/2 · TLS HTTP/2 · TLS 4,682
(104 MiB / 37.3% CPU)
4,682
(104 MiB / 37.3% CPU)
Not possible Not possible 3,969
(83 MiB / 24.5% CPU)
3,969
(83 MiB / 24.5% CPU)
🥇 6,266
(154 MiB / 23.0% CPU)
6,266
(154 MiB / 23.0% CPU)
6,174
(184 MiB / 46.0% CPU)
6,174
(184 MiB / 46.0% CPU)
64 KiB HTTP/3 · QUIC HTTP/2 · TLS 2,941
(168 MiB / 52.7% CPU)
2,941
(168 MiB / 52.7% CPU)
Not possible Not possible Not measured Not measured Not measured Not measured 🥇 3,040
(234 MiB / 48.9% CPU)
3,040
(234 MiB / 48.9% CPU)
64 KiB HTTP/3 · QUIC HTTP/1 · TLS 🥇 6,442
(214 MiB / 41.6% CPU)
6,442
(214 MiB / 41.6% CPU)
0
(145 MiB / 17.0% CPU)
2,278
(145 MiB / 17.0% CPU)
Not measured Not measured Not measured Not measured 4,761
(248 MiB / 49.0% CPU)
4,761
(248 MiB / 49.0% CPU)
256 KiB HTTP/2 · plain HTTP/1 · plain 3,918
(201 MiB / 33.0% CPU)
3,918
(201 MiB / 33.0% CPU)
1,946
(80 MiB / 14.2% CPU)
1,946
(80 MiB / 14.2% CPU)
4,300
(72 MiB / 18.6% CPU)
4,300
(72 MiB / 18.6% CPU)
🥇 4,479
(153 MiB / 21.0% CPU)
4,479
(153 MiB / 21.0% CPU)
3,945
(157 MiB / 38.1% CPU)
3,945
(157 MiB / 38.1% CPU)
256 KiB HTTP/2 · TLS HTTP/2 · plain 1,139
(111 MiB / 33.5% CPU)
1,139
(111 MiB / 33.5% CPU)
Not possible Not possible 0
(81 MiB / 19.8% CPU)
0
(81 MiB / 19.8% CPU)
0
(126 MiB / 22.3% CPU)
0
(126 MiB / 22.3% CPU)
🥇 1,293
(186 MiB / 42.8% CPU)
1,293
(186 MiB / 42.8% CPU)
256 KiB HTTP/2 · TLS HTTP/2 · TLS 1,436
(114 MiB / 28.9% CPU)
1,436
(114 MiB / 28.9% CPU)
Not possible Not possible 1,114
(89 MiB / 24.3% CPU)
1,114
(89 MiB / 24.3% CPU)
🥇 1,826
(160 MiB / 22.8% CPU)
1,826
(160 MiB / 22.8% CPU)
1,734
(185 MiB / 42.8% CPU)
1,734
(185 MiB / 42.8% CPU)
256 KiB HTTP/3 · QUIC HTTP/2 · TLS 837
(187 MiB / 51.5% CPU)
837
(187 MiB / 51.5% CPU)
Not possible Not possible Not measured Not measured Not measured Not measured 🥇 915
(246 MiB / 46.9% CPU)
915
(246 MiB / 46.9% CPU)
256 KiB HTTP/3 · QUIC HTTP/1 · TLS 🥇 1,745
(189 MiB / 42.2% CPU)
1,745
(189 MiB / 42.2% CPU)
0
(143 MiB / 18.7% CPU)
619
(143 MiB / 18.7% CPU)
Not measured Not measured Not measured Not measured 1,487
(249 MiB / 47.5% CPU)
1,487
(249 MiB / 47.5% CPU)

On this GHA pass TWP÷YARP H1 TLS ≈ 1.23× (64 KiB) / 1.28× (256 KiB); H2→H1 ≈ 1.23× / 1.16×; H3→H1 ≈ 1.27× / 1.13×. TWP÷nginx H1 TLS ≈ 1.43 / 1.58. Absolute RPS swings by VM; prefer ratios.

Windows — POST 64 KiB request + 64 KiB response

Windows heavier POST

Median of 3 repeats on windows-latest @ 9a2b3a1e. Source: Actions 34441591377 (compare-post).

Client Origin TWP sustain TWP peak nginx sustain nginx peak HAProxy sustain HAProxy peak Envoy sustain Envoy peak YARP sustain YARP peak
HTTP/1 · TLS HTTP/1 · plain 🥇 5,883
(94 MiB / 46.6% CPU)
5,883
(94 MiB / 46.6% CPU)
352
(142 MiB / 24.7% CPU)
352
(142 MiB / 24.7% CPU)
Not possible Not possible Not possible Not possible 4,093
(137 MiB / 55.7% CPU)
4,093
(137 MiB / 55.7% CPU)
HTTP/2 · TLS HTTP/1 · plain 🥇 3,997
(184 MiB / 49.3% CPU)
3,997
(184 MiB / 49.3% CPU)
352
(143 MiB / 24.7% CPU)
352
(143 MiB / 24.7% CPU)
Not possible Not possible Not possible Not possible 3,494
(134 MiB / 52.1% CPU)
3,494
(134 MiB / 52.1% CPU)
HTTP/3 · QUIC HTTP/1 · plain 🥇 2,039
(162 MiB / 40.4% CPU)
2,039
(162 MiB / 40.4% CPU)
Not possible (no QUIC) Not possible (no QUIC) Not possible Not possible Not possible Not possible 1,893
(203 MiB / 48.6% CPU)
1,893
(203 MiB / 48.6% CPU)
HTTP/2 · plain HTTP/1 · plain 🥇 6,237
(182 MiB / 46.1% CPU)
6,237
(182 MiB / 46.1% CPU)
1,622
(130 MiB / 24.6% CPU)
1,622
(130 MiB / 24.6% CPU)
Not possible Not possible Not possible Not possible 5,889
(125 MiB / 53.5% CPU)
5,889
(125 MiB / 53.5% CPU)
HTTP/2 · TLS HTTP/2 · plain 8
(83 MiB / 0.2% CPU)
8
(83 MiB / 0.2% CPU)
Not possible Not possible Not possible Not possible Not possible Not possible 🥇 3,602
(143 MiB / 49.3% CPU)
3,602
(143 MiB / 49.3% CPU)
HTTP/2 · TLS HTTP/2 · TLS 8
(88 MiB / 0.1% CPU)
8
(88 MiB / 0.1% CPU)
Not possible Not possible Not possible Not possible Not possible Not possible 🥇 2,837
(142 MiB / 46.8% CPU)
2,837
(142 MiB / 46.8% CPU)
HTTP/3 · QUIC HTTP/2 · TLS 1,769
(178 MiB / 44.3% CPU)
1,769
(178 MiB / 44.3% CPU)
Not possible Not possible Not possible Not possible Not possible Not possible 🥇 1,857
(194 MiB / 47.4% CPU)
1,857
(194 MiB / 47.4% CPU)
HTTP/3 · QUIC HTTP/1 · TLS 🥇 1,935
(175 MiB / 42.5% CPU)
1,935
(175 MiB / 42.5% CPU)
Not possible (no QUIC) Not possible (no QUIC) Not possible Not possible Not possible Not possible 1,768
(213 MiB / 47.8% CPU)
1,768
(213 MiB / 47.8% CPU)

TWP leads H1 POST (1.5× YARP), H2 POST (1.2× YARP), and H3 POST (~1.1× YARP).

Linux — POST 64 KiB request + 64 KiB response

Linux heavier POST

Median of 3 repeats @ 9a2b3a1e. Source: Actions 34441591377 (compare-post).

Client Origin TWP sustain TWP peak nginx sustain nginx peak HAProxy sustain HAProxy peak Envoy sustain Envoy peak YARP sustain YARP peak
HTTP/1 · TLS HTTP/1 · plain 5,113
(133 MiB / 43.7% CPU)
5,113
(133 MiB / 43.7% CPU)
4,029
(100 MiB / 48.2% CPU)
4,029
(100 MiB / 48.2% CPU)
5,273
(86 MiB / 40.5% CPU)
5,273
(86 MiB / 40.5% CPU)
🥇 5,337
(131 MiB / 40.4% CPU)
5,337
(131 MiB / 40.4% CPU)
3,410
(176 MiB / 54.5% CPU)
3,410
(176 MiB / 54.5% CPU)
HTTP/2 · TLS HTTP/1 · plain 🥇 3,356
(220 MiB / 47.1% CPU)
3,356
(220 MiB / 47.1% CPU)
1,563
(116 MiB / 21.2% CPU)
1,563
(116 MiB / 21.2% CPU)
2,012
(83 MiB / 24.0% CPU)
2,012
(83 MiB / 24.0% CPU)
0
(146 MiB / 20.5% CPU)
2,914
(146 MiB / 20.5% CPU)
2,767
(171 MiB / 47.9% CPU)
2,767
(171 MiB / 47.9% CPU)
HTTP/3 · QUIC HTTP/1 · plain 🥇 3,052
(226 MiB / 43.7% CPU)
3,052
(226 MiB / 43.7% CPU)
557
(110 MiB / 25.0% CPU)
557
(110 MiB / 25.0% CPU)
Not measured Not measured Not measured Not measured 2,778
(240 MiB / 49.2% CPU)
2,778
(240 MiB / 49.2% CPU)
HTTP/2 · plain HTTP/1 · plain 🥇 5,779
(234 MiB / 42.8% CPU)
5,779
(234 MiB / 42.8% CPU)
2,488
(94 MiB / 22.3% CPU)
2,488
(94 MiB / 22.3% CPU)
3,011
(70 MiB / 23.1% CPU)
3,011
(70 MiB / 23.1% CPU)
0
(134 MiB / 22.7% CPU)
5,195
(134 MiB / 22.7% CPU)
4,169
(161 MiB / 41.4% CPU)
4,169
(161 MiB / 41.4% CPU)
HTTP/2 · TLS HTTP/2 · plain 6
(118 MiB / 0.2% CPU)
6
(118 MiB / 0.2% CPU)
Not possible Not possible 0
(90 MiB / 23.7% CPU)
0
(90 MiB / 23.7% CPU)
0
(153 MiB / 22.1% CPU)
0
(153 MiB / 22.1% CPU)
🥇 2,620
(179 MiB / 46.6% CPU)
2,620
(179 MiB / 46.6% CPU)
HTTP/2 · TLS HTTP/2 · TLS 8
(115 MiB / 0.3% CPU)
8
(115 MiB / 0.3% CPU)
Not possible Not possible 1,216
(88 MiB / 24.6% CPU)
1,216
(88 MiB / 24.6% CPU)
🥇 2,222
(147 MiB / 23.3% CPU)
2,222
(147 MiB / 23.3% CPU)
2,085
(181 MiB / 46.1% CPU)
2,085
(181 MiB / 46.1% CPU)
HTTP/3 · QUIC HTTP/2 · TLS 🥇 1,999
(236 MiB / 49.4% CPU)
1,999
(236 MiB / 49.4% CPU)
Not possible Not possible Not measured Not measured Not measured Not measured 1,950
(245 MiB / 46.9% CPU)
1,950
(245 MiB / 46.9% CPU)
HTTP/3 · QUIC HTTP/1 · TLS 🥇 2,301
(253 MiB / 44.2% CPU)
2,301
(253 MiB / 44.2% CPU)
471
(120 MiB / 25.1% CPU)
471
(120 MiB / 25.1% CPU)
Not measured Not measured Not measured Not measured 2,138
(274 MiB / 47.8% CPU)
2,138
(274 MiB / 47.8% CPU)

Linux nginx H1/H2/H3 POST completed (nginx.org mainline). TWP÷YARP H1 ≈ 1.5×; H2 ≈ 1.3×; H3 ≈ 1.1×. TWP÷nginx H3 ≈ .

Windows — lossy / high-RTT (H2 HOL / H3 loss)

Windows heavier lossy

Userspace 5 ms one-way delay + 1% TCP connection stall (H1/H2) or UDP datagram drop (H3); 64 KiB GET. Median of 3 repeats on windows-latest @ 9a2b3a1e34441595456 (compare-lossy).

Client Origin TWP sustain TWP peak nginx sustain nginx peak HAProxy sustain HAProxy peak Envoy sustain Envoy peak YARP sustain YARP peak
HTTP/1 · TLS HTTP/1 · plain 🥇 663
(112 MiB / 3.0% CPU)
663
(112 MiB / 3.0% CPU)
652
(143 MiB / 16.4% CPU)
652
(143 MiB / 16.4% CPU)
Not possible Not possible Not possible Not possible 662
(121 MiB / 4.5% CPU)
662
(121 MiB / 4.5% CPU)
HTTP/2 · TLS HTTP/1 · plain 0
(120 MiB / 1.4% CPU)
86
(120 MiB / 1.4% CPU)
0
(142 MiB / 0.6% CPU)
17
(142 MiB / 0.6% CPU)
Not possible Not possible Not possible Not possible 0
(99 MiB / 0.8% CPU)
16
(99 MiB / 0.8% CPU)
HTTP/3 · QUIC HTTP/1 · plain 0
(67 MiB / 0.1% CPU)
0
(67 MiB / 0.1% CPU)
Not possible (no QUIC) Not possible (no QUIC) Not possible Not possible Not possible Not possible 0
(80 MiB / 0.0% CPU)
0
(80 MiB / 0.0% CPU)
HTTP/2 · plain HTTP/1 · plain 0
(130 MiB / 1.5% CPU)
89
(130 MiB / 1.5% CPU)
0
(128 MiB / 0.1% CPU)
17
(128 MiB / 0.1% CPU)
Not possible Not possible Not possible Not possible 0
(91 MiB / 0.7% CPU)
16
(91 MiB / 0.7% CPU)
HTTP/2 · TLS HTTP/2 · plain 0
(68 MiB / 0.6% CPU)
8
(68 MiB / 0.6% CPU)
Not possible Not possible Not possible Not possible Not possible Not possible 0
(100 MiB / 0.7% CPU)
16
(100 MiB / 0.7% CPU)
HTTP/2 · TLS HTTP/2 · TLS 0
(71 MiB / 0.2% CPU)
8
(71 MiB / 0.2% CPU)
Not possible Not possible Not possible Not possible Not possible Not possible 0
(99 MiB / 0.8% CPU)
16
(99 MiB / 0.8% CPU)
HTTP/3 · QUIC HTTP/2 · TLS 0
(70 MiB / 0.1% CPU)
0
(70 MiB / 0.1% CPU)
Not possible Not possible Not possible Not possible Not possible Not possible 0
(80 MiB / 0.0% CPU)
0
(80 MiB / 0.0% CPU)
HTTP/3 · QUIC HTTP/1 · TLS 0
(69 MiB / 0.0% CPU)
0
(69 MiB / 0.0% CPU)
Not possible (no QUIC) Not possible (no QUIC) Not possible Not possible Not possible Not possible 0
(78 MiB / 0.0% CPU)
0
(78 MiB / 0.0% CPU)

TWP H2 HOL leads (~3.31× YARP). H3 is the protocol-shape win vs H2 HOL on the same lossy session; Win H3 GHA remains 0 (laptop remeasure kept above).

Linux — lossy / high-RTT (H2 HOL / H3 loss)

Linux heavier lossy

Median of 3 repeats @ 9a2b3a1e. Source: 34441595456 (compare-lossy; lossy H3 uses quic-http3).

Client Origin TWP sustain TWP peak nginx sustain nginx peak HAProxy sustain HAProxy peak Envoy sustain Envoy peak YARP sustain YARP peak
HTTP/1 · TLS HTTP/1 · plain 1,195
(142 MiB / 13.7% CPU)
1,195
(142 MiB / 13.7% CPU)
1,205
(100 MiB / 12.6% CPU)
1,205
(100 MiB / 12.6% CPU)
🥇 1,207
(83 MiB / 7.8% CPU)
1,207
(83 MiB / 7.8% CPU)
1,193
(128 MiB / 9.3% CPU)
1,193
(128 MiB / 9.3% CPU)
1,194
(150 MiB / 17.5% CPU)
1,194
(150 MiB / 17.5% CPU)
HTTP/2 · TLS HTTP/1 · plain 🥇 314
(182 MiB / 7.0% CPU)
314
(182 MiB / 7.0% CPU)
40
(99 MiB / 0.3% CPU)
40
(99 MiB / 0.3% CPU)
40
(86 MiB / 0.3% CPU)
40
(86 MiB / 0.3% CPU)
40
(135 MiB / 0.4% CPU)
40
(135 MiB / 0.4% CPU)
40
(127 MiB / 1.5% CPU)
40
(127 MiB / 1.5% CPU)
HTTP/3 · QUIC HTTP/1 · plain 319
(151 MiB / 13.9% CPU)
319
(151 MiB / 13.9% CPU)
92
(109 MiB / 2.8% CPU)
92
(109 MiB / 2.8% CPU)
Not measured Not measured Not measured Not measured 🥇 338
(177 MiB / 22.4% CPU)
338
(177 MiB / 22.4% CPU)
HTTP/2 · plain HTTP/1 · plain 🥇 344
(174 MiB / 7.2% CPU)
344
(174 MiB / 7.2% CPU)
40
(78 MiB / 0.2% CPU)
40
(78 MiB / 0.2% CPU)
40
(69 MiB / 0.2% CPU)
40
(69 MiB / 0.2% CPU)
40
(129 MiB / 0.4% CPU)
40
(129 MiB / 0.4% CPU)
41
(121 MiB / 1.2% CPU)
41
(121 MiB / 1.2% CPU)
HTTP/2 · TLS HTTP/2 · plain 0
(93 MiB / 0.6% CPU)
13
(93 MiB / 0.6% CPU)
Not possible Not possible 0
(83 MiB / 2.7% CPU)
0
(83 MiB / 2.7% CPU)
0
(127 MiB / 6.3% CPU)
0
(127 MiB / 6.3% CPU)
🥇 40
(129 MiB / 1.6% CPU)
40
(129 MiB / 1.6% CPU)
HTTP/2 · TLS HTTP/2 · TLS 0
(95 MiB / 0.7% CPU)
11
(95 MiB / 0.7% CPU)
Not possible Not possible 🥇 42
(88 MiB / 0.6% CPU)
42
(88 MiB / 0.6% CPU)
40
(138 MiB / 0.5% CPU)
40
(138 MiB / 0.5% CPU)
40
(129 MiB / 1.6% CPU)
40
(129 MiB / 1.6% CPU)
HTTP/3 · QUIC HTTP/2 · TLS 322
(140 MiB / 24.2% CPU)
322
(140 MiB / 24.2% CPU)
Not possible Not possible Not measured Not measured Not measured Not measured 🥇 333
(183 MiB / 24.3% CPU)
333
(183 MiB / 24.3% CPU)
HTTP/3 · QUIC HTTP/1 · TLS 🥇 341
(161 MiB / 15.8% CPU)
341
(161 MiB / 15.8% CPU)
96
(113 MiB / 3.0% CPU)
96
(113 MiB / 3.0% CPU)
Not measured Not measured Not measured Not measured 340
(185 MiB / 23.1% CPU)
340
(185 MiB / 23.1% CPU)

TWP H2 HOL ≫ YARP (~7.7×). H3 TWP÷YARP ≈ .

Architecture-sensitive

Windows heavier architecture-sensitive workloads

Linux heavier architecture-sensitive workloads

These runs isolate slow app readers, origin-early response, HTTP/2 duplex, and WebSocket echo. See TWP vs YARP IO model. Laptop 1-rep numbers are on Performance Local Lab.

Median of 3 repeats on matched 4 vCPU / 16 GiB runners @ 9a2b3a1e (34441578556). Slow consumer = 256 KiB GET, 16 KiB read + 8 ms sleep. Early response = 64 KiB POST, origin writes after 8 KiB. Duplex HTTP/2 = overlapping 64 KiB POST on H2 TLS↔H2 TLS. WebSocket = echo round-trips/sec.

Lossy-link runs (slow network) are already published above; they are not a slow app reader.

Windows

Windows heavier arch

Scenario Client Origin TWP sustain TWP peak nginx sustain nginx peak HAProxy sustain HAProxy peak Envoy sustain Envoy peak YARP sustain YARP peak
Slow consumer (256 KiB GET, throttled client read) HTTP/1 · TLS HTTP/1 · plain 🥇 243
(101 MiB / 5.9% CPU)
243
(101 MiB / 5.9% CPU)
204
(143 MiB / 24.6% CPU)
204
(143 MiB / 24.6% CPU)
Not possible Not possible Not possible Not possible 241
(109 MiB / 4.8% CPU)
241
(109 MiB / 4.8% CPU)
Slow consumer (256 KiB GET, throttled client read) HTTP/2 · TLS HTTP/1 · plain 256
(131 MiB / 3.7% CPU)
256
(131 MiB / 3.7% CPU)
230
(142 MiB / 24.4% CPU)
230
(142 MiB / 24.4% CPU)
Not possible Not possible Not possible Not possible 🥇 256
(111 MiB / 5.4% CPU)
256
(111 MiB / 5.4% CPU)
Slow consumer (256 KiB GET, throttled client read) HTTP/3 · QUIC HTTP/1 · plain 🥇 264
(101 MiB / 17.4% CPU)
264
(101 MiB / 17.4% CPU)
Not possible (no QUIC) Not possible (no QUIC) Not possible Not possible Not possible Not possible 255
(158 MiB / 20.4% CPU)
255
(158 MiB / 20.4% CPU)
Early response (origin writes after first request chunk) HTTP/1 · TLS HTTP/1 · plain 🥇 5,611
(99 MiB / 45.5% CPU)
5,611
(99 MiB / 45.5% CPU)
363
(143 MiB / 24.7% CPU)
363
(143 MiB / 24.7% CPU)
Not possible Not possible Not possible Not possible 3,919
(138 MiB / 53.9% CPU)
3,919
(138 MiB / 53.9% CPU)
Early response (origin writes after first request chunk) HTTP/2 · TLS HTTP/1 · plain 🥇 3,934
(169 MiB / 48.8% CPU)
3,934
(169 MiB / 48.8% CPU)
0
(144 MiB / 24.8% CPU)
318
(144 MiB / 24.8% CPU)
Not possible Not possible Not possible Not possible 3,200
(135 MiB / 53.4% CPU)
3,200
(135 MiB / 53.4% CPU)
Early response (origin writes after first request chunk) HTTP/3 · QUIC HTTP/1 · plain 🥇 3,012
(152 MiB / 42.0% CPU)
3,012
(152 MiB / 42.0% CPU)
Not possible (no QUIC) Not possible (no QUIC) Not possible Not possible Not possible Not possible 2,602
(203 MiB / 51.0% CPU)
2,602
(203 MiB / 51.0% CPU)
Slow consumer (256 KiB GET, throttled client read) HTTP/2 · plain HTTP/1 · plain 248
(112 MiB / 3.6% CPU)
248
(112 MiB / 3.6% CPU)
248
(127 MiB / 9.4% CPU)
248
(127 MiB / 9.4% CPU)
Not possible Not possible Not possible Not possible 🥇 256
(104 MiB / 6.0% CPU)
256
(104 MiB / 6.0% CPU)
Slow consumer (256 KiB GET, throttled client read) HTTP/2 · TLS HTTP/2 · TLS 0
(70 MiB / 1.0% CPU)
8
(70 MiB / 1.0% CPU)
Not possible Not possible Not possible Not possible Not possible Not possible 🥇 256
(136 MiB / 9.3% CPU)
256
(136 MiB / 9.3% CPU)
Early response (origin writes after first request chunk) HTTP/2 · TLS HTTP/2 · TLS 0
(92 MiB / 0.1% CPU)
0
(92 MiB / 0.1% CPU)
Not possible Not possible Not possible Not possible Not possible Not possible 0
(110 MiB / 0.1% CPU)
0
(110 MiB / 0.1% CPU)
Duplex (both directions live) HTTP/2 · TLS HTTP/2 · TLS 0
(91 MiB / 0.1% CPU)
0
(91 MiB / 0.1% CPU)
Not possible Not possible Not possible Not possible Not possible Not possible 0
(111 MiB / 0.1% CPU)
0
(111 MiB / 0.1% CPU)
Duplex (WebSocket / extended CONNECT) HTTP/1 · TLS HTTP/1 · plain 🥇 24,498
(97 MiB / 43.0% CPU)
24,498
(97 MiB / 43.0% CPU)
12,337
(143 MiB / 24.6% CPU)
12,337
(143 MiB / 24.6% CPU)
Not possible Not possible Not possible Not possible 23,100
(89 MiB / 44.6% CPU)
23,100
(89 MiB / 44.6% CPU)

Linux

Linux heavier arch

Scenario Client Origin TWP sustain TWP peak nginx sustain nginx peak HAProxy sustain HAProxy peak Envoy sustain Envoy peak YARP sustain YARP peak
Slow consumer (256 KiB GET, throttled client read) HTTP/1 · TLS HTTP/1 · plain 469
(122 MiB / 9.7% CPU)
469
(122 MiB / 9.7% CPU)
411
(100 MiB / 9.9% CPU)
411
(100 MiB / 9.9% CPU)
466
(83 MiB / 6.0% CPU)
466
(83 MiB / 6.0% CPU)
🥇 470
(140 MiB / 6.2% CPU)
470
(140 MiB / 6.2% CPU)
411
(146 MiB / 14.2% CPU)
411
(146 MiB / 14.2% CPU)
Slow consumer (256 KiB GET, throttled client read) HTTP/2 · TLS HTTP/1 · plain 🥇 480
(149 MiB / 13.1% CPU)
480
(149 MiB / 13.1% CPU)
374
(102 MiB / 5.0% CPU)
374
(102 MiB / 5.0% CPU)
475
(85 MiB / 4.3% CPU)
475
(85 MiB / 4.3% CPU)
477
(149 MiB / 4.5% CPU)
477
(149 MiB / 4.5% CPU)
477
(146 MiB / 15.0% CPU)
477
(146 MiB / 15.0% CPU)
Slow consumer (256 KiB GET, throttled client read) HTTP/3 · QUIC HTTP/1 · plain 🥇 473
(131 MiB / 34.1% CPU)
473
(131 MiB / 34.1% CPU)
0
(119 MiB / 21.9% CPU)
122
(119 MiB / 21.9% CPU)
Not measured Not measured Not measured Not measured 468
(198 MiB / 39.8% CPU)
468
(198 MiB / 39.8% CPU)
Early response (origin writes after first request chunk) HTTP/1 · TLS HTTP/1 · plain 4,671
(132 MiB / 47.4% CPU)
4,671
(132 MiB / 47.4% CPU)
0
(100 MiB / 49.6% CPU)
3,397
(100 MiB / 49.6% CPU)
🥇 4,886
(84 MiB / 43.3% CPU)
4,886
(84 MiB / 43.3% CPU)
0
(129 MiB / 25.6% CPU)
2,584
(129 MiB / 25.6% CPU)
3,159
(176 MiB / 56.3% CPU)
3,159
(176 MiB / 56.3% CPU)
Early response (origin writes after first request chunk) HTTP/2 · TLS HTTP/1 · plain 🥇 3,266
(242 MiB / 48.3% CPU)
3,266
(242 MiB / 48.3% CPU)
0
(113 MiB / 24.7% CPU)
1,365
(113 MiB / 24.7% CPU)
2,480
(85 MiB / 24.6% CPU)
2,480
(85 MiB / 24.6% CPU)
0
(148 MiB / 23.9% CPU)
2,653
(148 MiB / 23.9% CPU)
2,198
(169 MiB / 48.3% CPU)
2,198
(169 MiB / 48.3% CPU)
Early response (origin writes after first request chunk) HTTP/3 · QUIC HTTP/1 · plain 🥇 4,504
(218 MiB / 43.2% CPU)
4,504
(218 MiB / 43.2% CPU)
0
(125 MiB / 22.7% CPU)
1,090
(125 MiB / 22.7% CPU)
Not measured Not measured Not measured Not measured 3,217
(274 MiB / 48.7% CPU)
3,217
(274 MiB / 48.7% CPU)
Slow consumer (256 KiB GET, throttled client read) HTTP/2 · plain HTTP/1 · plain 🥇 478
(136 MiB / 15.5% CPU)
478
(136 MiB / 15.5% CPU)
360
(79 MiB / 8.6% CPU)
360
(79 MiB / 8.6% CPU)
473
(69 MiB / 6.4% CPU)
473
(69 MiB / 6.4% CPU)
473
(147 MiB / 4.7% CPU)
473
(147 MiB / 4.7% CPU)
475
(150 MiB / 16.2% CPU)
475
(150 MiB / 16.2% CPU)
Slow consumer (256 KiB GET, throttled client read) HTTP/2 · TLS HTTP/2 · TLS 8
(97 MiB / 2.5% CPU)
8
(97 MiB / 2.5% CPU)
Not possible Not possible 455
(89 MiB / 22.6% CPU)
455
(89 MiB / 22.6% CPU)
466
(152 MiB / 12.9% CPU)
466
(152 MiB / 12.9% CPU)
🥇 466
(168 MiB / 31.1% CPU)
466
(168 MiB / 31.1% CPU)
Early response (origin writes after first request chunk) HTTP/2 · TLS HTTP/2 · TLS 0
(112 MiB / 0.1% CPU)
0
(112 MiB / 0.1% CPU)
Not possible Not possible Not measured Not measured 0
(156 MiB / 19.5% CPU)
3,680
(156 MiB / 19.5% CPU)
0
(146 MiB / 0.2% CPU)
0
(146 MiB / 0.2% CPU)
Duplex (both directions live) HTTP/2 · TLS HTTP/2 · TLS 0
(112 MiB / 0.1% CPU)
0
(112 MiB / 0.1% CPU)
Not possible Not possible 0
(91 MiB / 0.1% CPU)
0
(91 MiB / 0.1% CPU)
0
(151 MiB / 19.4% CPU)
3,724
(151 MiB / 19.4% CPU)
0
(151 MiB / 0.1% CPU)
0
(151 MiB / 0.1% CPU)
Duplex (WebSocket / extended CONNECT) HTTP/1 · TLS HTTP/1 · plain 28,567
(125 MiB / 44.0% CPU)
28,567
(125 MiB / 44.0% CPU)
🥇 33,775
(100 MiB / 35.5% CPU)
33,775
(100 MiB / 35.5% CPU)
31,870
(84 MiB / 39.3% CPU)
31,870
(84 MiB / 39.3% CPU)
31,525
(127 MiB / 39.4% CPU)
31,525
(127 MiB / 39.4% CPU)
27,109
(125 MiB / 44.1% CPU)
27,109
(125 MiB / 44.1% CPU)

Slow consumer is sleep-bound; H1/H2/H3 sit in the same band. Early-response H1/H2/H3: TWP leads (H1 early ≈ 2.00× / 1.47× YARP Win/Linux). Duplex H2: YARP leads by design — Win ≈ 0.59× (1,270 / 2,135), Linux ≈ 0.15× (282 / 1,882); irreducible concurrent-copier cell (see IO model). WebSocket: TWP÷YARP Windows ≈ 1.06×; Linux nginx leads.

TLS termination cost (H1 TLS → cleartext origin)

Isolates keep-alive tiny GET vs new connection per request (handshake-dominated) vs keep-alive 256 KiB. Product comparison uses RPS and end-to-end latency; TWP can also capture ClientTlsTiming when TWP_RPS_CAPTURE_TLS=1 (child process) — nginx/YARP have no equivalent hook.

Windows TLS termination cost

Linux TLS termination cost

Windows

Median of 3 repeats on windows-latest @ 9a2b3a1e. Source: Actions 34441599658. Absolute RPS on GHA swings hard; prefer TWP÷YARP.

Windows heavier TLS cost

Workload TWP sustain TWP peak nginx sustain nginx peak HAProxy sustain HAProxy peak Envoy sustain Envoy peak YARP sustain YARP peak
Keep-alive · tiny GET 🥇 20,612
(87 MiB / 47.9% CPU)
20,612
(87 MiB / 47.9% CPU)
8,972
(142 MiB / 24.8% CPU)
8,972
(142 MiB / 24.8% CPU)
Not possible Not possible Not possible Not possible 18,392
(105 MiB / 50.9% CPU)
18,392
(105 MiB / 50.9% CPU)
New-connection · tiny GET 🥇 732
(88 MiB / 9.5% CPU)
732
(88 MiB / 9.5% CPU)
0
(140 MiB / 24.4% CPU)
248
(140 MiB / 24.4% CPU)
Not possible Not possible Not possible Not possible 725
(113 MiB / 10.7% CPU)
725
(113 MiB / 10.7% CPU)
Keep-alive · 256 KiB GET 🥇 2,741
(130 MiB / 47.0% CPU)
2,741
(130 MiB / 47.0% CPU)
0
(142 MiB / 24.6% CPU)
162
(142 MiB / 24.6% CPU)
Not possible Not possible Not possible Not possible 2,699
(136 MiB / 49.4% CPU)
2,699
(136 MiB / 49.4% CPU)

Linux

Median of 3 repeats @ 9a2b3a1e. Source: Actions 34441599658.

Linux heavier TLS cost

Workload TWP sustain TWP peak nginx sustain nginx peak HAProxy sustain HAProxy peak Envoy sustain Envoy peak YARP sustain YARP peak
Keep-alive · tiny GET 36,114
(108 MiB / 49.4% CPU)
36,114
(108 MiB / 49.4% CPU)
🥇 44,372
(102 MiB / 40.8% CPU)
44,372
(102 MiB / 40.8% CPU)
43,256
(84 MiB / 43.3% CPU)
43,256
(84 MiB / 43.3% CPU)
27,636
(128 MiB / 57.3% CPU)
27,636
(128 MiB / 57.3% CPU)
32,712
(135 MiB / 49.8% CPU)
32,712
(135 MiB / 49.8% CPU)
New-connection · tiny GET 1,549
(128 MiB / 40.0% CPU)
1,549
(128 MiB / 40.0% CPU)
🥇 1,598
(103 MiB / 36.2% CPU)
1,598
(103 MiB / 36.2% CPU)
1,454
(85 MiB / 37.7% CPU)
1,454
(85 MiB / 37.7% CPU)
1,379
(129 MiB / 44.5% CPU)
1,379
(129 MiB / 44.5% CPU)
1,525
(149 MiB / 38.9% CPU)
1,525
(149 MiB / 38.9% CPU)
Keep-alive · 256 KiB GET 3,790
(126 MiB / 31.8% CPU)
3,790
(126 MiB / 31.8% CPU)
2,421
(101 MiB / 48.7% CPU)
2,421
(101 MiB / 48.7% CPU)
🥇 3,940
(84 MiB / 28.4% CPU)
3,940
(84 MiB / 28.4% CPU)
3,544
(145 MiB / 32.3% CPU)
3,544
(145 MiB / 32.3% CPU)
3,031
(160 MiB / 42.1% CPU)
3,031
(160 MiB / 42.1% CPU)

All three workloads are >1.00× YARP on both OS. nginx leads Linux keep-alive tiny and Linux new-connection; TWP is second, YARP third.

Unary gRPC (H2 TLS)

Unary Echo RPC/s @ c=64 over H2 TLS→H2 TLS for Titanium, YARP, nginx (grpc_pass), HAProxy, and Envoy (OS-possible peers only). Not folded into the architecture-sensitive tables. Median of 3 repeats @ 9a2b3a1e34441548073.

OS Titanium YARP nginx HAProxy Envoy
Windows 53,762
(88 MiB / 23.6% CPU)
30,754
(123 MiB / 46.9% CPU)
Not measured Not possible Not possible
Linux 42,675
(120 MiB / 30.3% CPU)
24,232
(159 MiB / 41.6% CPU)
Not measured 8,683
(84 MiB / 24.6% CPU)
16,110
(128 MiB / 20.6% CPU)
macOS 14,924
(94 MiB / 20.1% CPU)
8,581
(128 MiB / 28.4% CPU)
Not measured Not measured Not measured

Other measurements

What Result
HTTPS TTFB vs direct (median, 14 hosts) Cold ≈ parity (−1 ms); warm −25 ms (proxy faster)
HTTP/1 loopback GET (no body intercept) ~128 µs, ~9.9 KB allocated / request
Basic example footprint (Release, after load) ~74 MB working set · ~24–29 MB private bytes
dotnet run -c Release --project benchmarks/Titanium.Web.Proxy.Benchmarks -- --filter '*Throughput*'

Local laptop BDN @ 9d7c2966 (Release):

Benchmark Setup Mean Allocated / op
HTTP/1 GET through proxy Passthrough 128 µs 9.9 KB
HTTP/2 multiplexed GETs 10 concurrent streams 253 µs / batch ~4.4 KB / request

Raising limits on large hosts

There is no artificial upper clamp on server defaults. Per-endpoint overrides:

Knob Scope Default Override
ProxyServer.MaxCachedConnections process, per upstream host 128 any ≥ 1
ProxyEndPoint.MaxCachedConnections endpoint → pool depth for that EP’s sessions null (use server) e.g. 256 on reverse EP
ProxyEndPoint.MaxConcurrentClients endpoint admission null (off) any ≥ 1
ResourceLimits.MaxConcurrentStreamsPerConnection H2 streams 256 ProxyResourceLimits.Create(...)
TransparentQuicProxyEndPoint.MaxInboundBidirectionalStreams H3 100 (probe uses 256) property on EP
ForwardCleartext transparent TLS terminate false true + decrypt
proxy.MaxCachedConnections = 512;
proxy.ResourceLimits = ProxyResourceLimits.Create(
    /* … */,
    maxConcurrentStreamsPerConnection: 1000,
    maxCachedConnectionsPerHost: 512,
    /* … */);

var ep = new TransparentProxyEndPoint(IPAddress.Any, 443, decryptSsl: true)
{
    ForwardHost = "127.0.0.1",
    ForwardPort = 8080,
    ForwardCleartext = true,
    MaxCachedConnections = 256,
    GenericCertificateName = "example.com"
};
ep.BeforeSslAuthenticate += (_, a) =>
{
    a.UpstreamHttpProtocol = UpstreamHttpProtocol.Http11;
    a.AllowHttpProtocolTranslation = true; // HTTP/2 client → HTTP/1 origin
    return Task.CompletedTask;
};

Maintainer notes

CI cadence, shards, paste scripts, and gate floors for people refreshing these tables. Consumers can skip this section.

Tiered cadence

Tier Mode When
Daily / per-PR compare-spot minutes
Milestone compare-terminate / compare-matrix ~1–2h
Editions compare-editions ~60 min (CLI / Plus / Intercept stress arms)
Cross-version (Gate 2) compare-cross-version ~1–2h vs committed 6.0 baselines
Pre-wiki smoke compare-product-smoke (Linux 2 shards, repeats=1) ~30–60 min; required before full product
Release / wiki compare-product (3 comparison-group shards × Win/Linux/mac) ~2–2½h wall (Free account queues beyond 20 jobs)
Unary gRPC compare-grpc Win/Linux/mac; RPC/s @ c=64
Heavier tables compare-bodies (2 shards) / post / lossy / arch (3 shards) / tls-cost dispatch independently

See PERF-GATES.md.

Arm shards (comparison groups)

--arm-shard i/n (workflow input arm_shard) partitions wiki rows (Client×Origin + heavier/arch workload suffix), not individual proxy arms. Paste unions shard CSVs (paste-compare-product-wiki.ps1 -RunIds …; heavier RUNS lists). Table “Source: Actions” may list several run URLs for one table — do not mix SHAs. Free GitHub accounts allow 20 concurrent jobs (~34 for a full suite); extras queue, they do not fail. Dispatch product (and cross-version) first when wall clock matters.

One wiki row = one GHA job’s Client×Origin cell set: TWP + YARP + nginx + HAProxy + Envoy (when the OS can run them) + TWP Lite + Full stay on the same VM. Shards split rows, not individual proxies — so TWP÷YARP and Lite÷Reverse remain same-job ratios. Do not compare absolute RPS across shards (different VMs).

Gate thresholds

  • Reverse product signal: TWP÷YARP ≥ 0.70 (nginx / HAProxy / Envoy are wiki and chart peers only — no CI gate).
  • MITM overhead: Lite÷Reverse ≥ 0.50 and Full÷Reverse ≥ 0.50 (median of 3 GHA runs @ c=64). Absolute RPS moves with runner heat; ratios are the claim.
  • Editions: see PERF-GATES.md and validate-edition-gates.ps1.
  • Cross-version (Gate 2) before a major tag: run compare-cross-version (reverse matrix, routes unset) on develop vs committed 6.0 baselines (baseline-6.0-win.csv / baseline-6.0-linux.csv).
Gate Threshold
Peer-normalized RPS (when YARP peer exists) (TWP÷YARP)_7 ÷ (TWP÷YARP)_6 ≥ 0.90 or current (TWP÷YARP) ≥ 0.90
Absolute RPS floor (TWP arms) 7.0 ÷ 6.0 ≥ 0.70 (runner heat — peers move with the box)
RSS 7.0 ÷ 6.0 ≤ 1.20 per TWP arm @ c=64

nginx/YARP absolute RPS is not gated. See validate-cross-version.ps1.

pwsh tools/RpsLoadProbe/run-rps.ps1 -Mode compare-cross-version
pwsh tools/RpsLoadProbe/validate-cross-version.ps1 `
  -BaselineCsv tools/RpsLoadProbe/results/baseline-6.0-win.csv `
  -CurrentCsv  tools/RpsLoadProbe/results/rps-ramp-*.csv

Paste / regenerate

Product refresh and heavier tables:

pwsh tools/RpsLoadProbe/run-rps.ps1 -Mode compare-product
pwsh tools/RpsLoadProbe/run-rps.ps1 -Mode compare-editions
pwsh tools/RpsLoadProbe/validate-edition-gates.ps1 -CsvPath tools/RpsLoadProbe/results/rps-ramp-*.csv
pwsh tools/RpsLoadProbe/run-rps.ps1 -Mode compare-bodies
pwsh tools/RpsLoadProbe/run-rps.ps1 -Mode compare-post
pwsh tools/RpsLoadProbe/run-rps.ps1 -Mode compare-lossy
pwsh tools/RpsLoadProbe/run-rps.ps1 -Mode compare-tls-cost
pwsh tools/RpsLoadProbe/run-rps.ps1 -Mode compare-arch
pwsh tools/RpsLoadProbe/run-rps.ps1 -Mode compare-saturation

Harness details: RpsLoadProbe. The harness does not disable TWP safety that peers also skip, and it does not retune to pass gates (PERF-GATES.md). MITM leaf keys are a shared RSA/ECDSA pair per CertificateManager (intentional RPS tradeoff).

Clone this wiki locally