Benchmarks
A tunnel can run over UDP or TCP (see Transport Modes). These benchmarks measure how that choice affects throughput and latency for traffic flowing through a tunnel, especially as network conditions degrade.
tl;dr
UDP outperforms TCP on lossy, unpredictable networks — degraded wifi, mobile tethering, unstable VPNs, anything over the internet.
TCP has a raw throughput advantage on stable, predictable, low-latency networks where packet loss is not a concern.
The five most telling scenarios:
| Scenario | UDP transport | TCP transport |
|---|---|---|
| No loss, no latency (1 connection) | 830 Mbps | 900 Mbps |
| No loss, high latency — 150 ms one-way, ~Singapore to London (32 connections) | 134 Mbps | 59 Mbps |
| 1% loss, cross-country — 40 ms one-way (32 connections) | 49 Mbps | 45 Mbps |
| 1% loss, cross-country — 40 ms one-way (128 connections) | 95 Mbps | 0 Mbps |
| 5% loss, cross-country — 40 ms one-way (128 connections) | 90 Mbps | 0 Mbps |
No Packet Loss or Latency
Single Connection
| Metric | UDP transport | TCP transport |
|---|---|---|
| TCP traffic upstream (to exit) | 830 Mbps | 900 Mbps |
| TCP traffic downstream (to entry) | 300 Mbps | 330 Mbps |
| UDP traffic | 5.3 Gbps | 4.5 Gbps |
| Latency (RTT) | 0.7 ms | 1.1 ms |
TCP is slightly faster for throughput. UDP has meaningfully lower latency. Downstream is lower than upstream because traffic arriving at the entry node requires extra processing to reconstruct into TCP connections.
Parallel Connections
| Connections | UDP transport | TCP transport |
|---|---|---|
| 32 | 794 Mbps | 932 Mbps |
| 64 | 744 Mbps | 896 Mbps |
| 128 | 578 Mbps | 815 Mbps |
With Packet Loss and Latency
Varying Loss
32 connections — a few parallel scans, SSH sessions, or file transfers.
| Loss | Delay (one-way) | UDP transport | TCP transport |
|---|---|---|---|
| 0.1% | 40 ms | 110 Mbps | 66 Mbps |
| 0.5% | 40 ms | 54 Mbps | 48 Mbps |
| 1% | 40 ms | 49 Mbps | 45 Mbps |
| 2% | 40 ms | 52 Mbps | 46 Mbps |
| 3% | 40 ms | 51 Mbps | 43 Mbps |
| 5% | 40 ms | 49 Mbps | 46 Mbps |
Both transports survive at 32 connections, but the UDP transport is consistently faster.
64 connections — multiple scans in parallel, several RDP or SSH sessions.
| Loss | Delay (one-way) | UDP transport | TCP transport |
|---|---|---|---|
| 0.1% | 40 ms | 103 Mbps | 71 Mbps |
| 0.5% | 40 ms | 68 Mbps | 66 Mbps |
| 1% | 40 ms | 69 Mbps | 68 Mbps |
| 2% | 40 ms | 67 Mbps | 62 Mbps |
| 3% | 40 ms | 66 Mbps | 66 Mbps |
| 5% | 40 ms | 63 Mbps | 0 Mbps |
The TCP transport drops to zero throughput at 5% loss. The UDP transport maintains throughput.
128 connections — dictionary attacks, full nmap scans, mass HTTP requests.
| Loss | Delay (one-way) | UDP transport | TCP transport |
|---|---|---|---|
| 0.1% | 40 ms | 150 Mbps | 112 Mbps |
| 0.5% | 40 ms | 92 Mbps | 0 Mbps |
| 1% | 40 ms | 95 Mbps | 0 Mbps |
| 2% | 40 ms | 91 Mbps | 0 Mbps |
| 3% | 40 ms | 93 Mbps | 0 Mbps |
| 5% | 40 ms | 90 Mbps | 0 Mbps |
At 128 connections, the TCP transport collapses at very low packet loss. The UDP transport maintains throughput across all tested loss rates.
Varying Latency
32 connections
| Loss | Delay (one-way) | UDP transport | TCP transport |
|---|---|---|---|
| 1% | 1 ms | 67 Mbps | 107 Mbps |
| 1% | 10 ms | 62 Mbps | 56 Mbps |
| 1% | 20 ms | 54 Mbps | 45 Mbps |
| 1% | 40 ms | 54 Mbps | 48 Mbps |
| 1% | 80 ms | 52 Mbps | 43 Mbps |
| 1% | 150 ms | 52 Mbps | 38 Mbps |
The TCP transport is faster at very low latency. As latency increases, the UDP transport takes over. Both survive across all latencies at 32 connections.
64 connections
| Loss | Delay (one-way) | UDP transport | TCP transport |
|---|---|---|---|
| 1% | 1 ms | 95 Mbps | 69 Mbps |
| 1% | 10 ms | 72 Mbps | 68 Mbps |
| 1% | 20 ms | 68 Mbps | 66 Mbps |
| 1% | 40 ms | 67 Mbps | 67 Mbps |
| 1% | 80 ms | 66 Mbps | 64 Mbps |
| 1% | 150 ms | 60 Mbps | 0 Mbps |
At high latency, the TCP transport produces zero throughput.
128 connections
| Loss | Delay (one-way) | UDP transport | TCP transport |
|---|---|---|---|
| 1% | 1 ms | 165 Mbps | 105 Mbps |
| 1% | 10 ms | 106 Mbps | 107 Mbps |
| 1% | 20 ms | 99 Mbps | 0 Mbps |
| 1% | 40 ms | 95 Mbps | 0 Mbps |
| 1% | 80 ms | 97 Mbps | 0 Mbps |
| 1% | 150 ms | 90 Mbps | 0 Mbps |
The TCP transport drops to zero throughput beyond low latency. The UDP transport remains stable across all latencies.
Varying Latency, No Loss
32 connections
| Loss | Delay (one-way) | UDP transport | TCP transport |
|---|---|---|---|
| 0% | 1 ms | 394 Mbps | 653 Mbps |
| 0% | 10 ms | 142 Mbps | 429 Mbps |
| 0% | 40 ms | 146 Mbps | 110 Mbps |
| 0% | 80 ms | 135 Mbps | 95 Mbps |
| 0% | 150 ms | 134 Mbps | 59 Mbps |
64 connections
| Loss | Delay (one-way) | UDP transport | TCP transport |
|---|---|---|---|
| 0% | 1 ms | 345 Mbps | 1039 Mbps |
| 0% | 10 ms | 149 Mbps | 449 Mbps |
| 0% | 40 ms | 163 Mbps | 101 Mbps |
| 0% | 80 ms | 150 Mbps | 70 Mbps |
| 0% | 150 ms | 145 Mbps | 68 Mbps |
128 connections
| Loss | Delay (one-way) | UDP transport | TCP transport |
|---|---|---|---|
| 0% | 1 ms | 379 Mbps | 687 Mbps |
| 0% | 10 ms | 175 Mbps | 447 Mbps |
| 0% | 40 ms | 176 Mbps | 155 Mbps |
| 0% | 80 ms | 171 Mbps | 112 Mbps |
| 0% | 150 ms | 195 Mbps | 108 Mbps |
Without loss, the TCP transport wins at low latency. As latency increases, the UDP transport takes over and the gap widens.
TCP Advantages
Strengths
Benefits from the OS kernel's highly optimised TCP stack. On stable, low-latency networks with negligible packet loss, it reaches gigabit-class throughput. At very low latency (e.g. same data centre), it outperforms UDP by a meaningful margin. It also traverses HTTP proxies and CDN infrastructure via WebSocket, which UDP cannot.
Trade-offs
Multiplexes all tunnel connections over a single TCP connection — one port, one connection, one queue. When a packet at the front of that queue is lost, every connection behind it has to wait for the retransmission. The more connections sharing the queue, the more likely any single packet loss stalls everything. This is called head-of-line blocking, and it is a fundamental property of TCP — not a flaw in the WebSocket transport itself.
UDP Advantages
Strengths
Under the hood, QUIC gives each tunnel connection its own independent stream. A lost packet only stalls the affected connection. Everything else continues uninterrupted. More connections means more independent recovery paths, which is why UDP throughput scales with connection count under loss while TCP throughput drops to zero.
Trade-offs
Slightly lower raw throughput on clean, low-latency networks compared to TCP.
Methodology
Traffic is generated with iperf3 through a full end-to-end tunnel with encryption active. Entry and exit run as QEMU microVMs on the same host with KVM. Throughput values are medians across multiple runs.
Packet loss and latency scenarios use tc netem on the entry VM's ethernet interface. Loss is applied on egress. All delay values are one-way — double them to get round-trip time.
To reproduce: just bench benchmark from the repo root. The benchmark harness, VM images, and network emulation scripts are all in the repository.