Enterprises frequently provision premium 10Gbps or 100Gbps Dedicated Internet Access (DIA) or inter-site data centre circuits (e.g. London Telehouse to Frankfurt Equinix), only to discover that a single-stream file transfer (`rsync`, `scp`, or backup snapshot) flatlines at roughly 380 to 450 Mbps. The interface is operating at 10Gbps, optical levels are nominal, and CPU utilization is near zero—yet 95% of link capacity sits idle.
The root cause is structural: TCP receive window exhaustion combined with physical round-trip time (RTT) latency. Without tuned socket buffers and RFC 7323 window scaling, TCP cannot keep sufficient data in transit to saturate a multi-gigabit pipe.
The 64KB Hard Ceiling: Why Legacy TCP Stalls
The original TCP specification (RFC 793) allocated a 16-bit integer field in the packet header for the Receive Window (`rwnd`). This established a strict maximum window size of:
2^16 - 1 = 65,535 bytes (64 KB)In a TCP transaction, the sender cannot transmit more data than the receiver's advertised window without waiting for an Acknowledgement (ACK). Consequently, the absolute maximum theoretical throughput of unscaled TCP is bounded by:
Throughput (bps) = (TCP Receive Window in Bits) / (Round-Trip Time in Seconds)Consider a typical enterprise circuit with an unscaled 64KB window across increasing latencies:
- London Metro (1.5ms RTT):
(65,535 × 8) / 0.0015 = 349.5 Mbps(tolerable for 1G, but caps a 10G link at 3.5% capacity). - London to Frankfurt (14ms RTT):
(65,535 × 8) / 0.014 = 37.4 Mbps(99.6% of a 10G link is wasted). - London to New York (68ms transatlantic RTT):
(65,535 × 8) / 0.068 = 7.7 Mbps(single-stream throughput collapses completely).
Calculating the Bandwidth-Delay Product (BDP)
The Bandwidth-Delay Product defines the volume of data that can be in flight across the network path simultaneously—the pipeline volume:
BDP (Bytes) = [ Bandwidth (bits/sec) × RTT (seconds) ] / 8To achieve line-rate saturation, the send and receive socket buffers on both endpoints must be at least equal to the path's BDP:
- 10Gbps at 15ms RTT (UK to Europe):
(10,000,000,000 × 0.015) / 8 = 18.75 MBbuffer required. - 10Gbps at 70ms RTT (UK to US East):
(10,000,000,000 × 0.070) / 8 = 87.5 MBbuffer required. - 100Gbps at 25ms RTT (Inter-DC Fabric):
(100,000,000,000 × 0.025) / 8 = 312.5 MBbuffer required.
Model Your WAN Bandwidth-Delay Product & Socket Limits
Calculate exact BDP buffer requirements, single-stream TCP ceilings, and encapsulation MTU overhead with our live engineering tool:
RFC 7323: The TCP Window Scale Option
To overcome the 16-bit 64KB limitation, RFC 7323 (which superseded RFC 1323) introduces the TCP Window Scale option negotiated during the three-way handshake (`SYN` packets).
The scale factor is a 1-byte shift count (from 0 to 14). A scale factor of 7 multiplies the 16-bit window value by 2^7 = 128. A maximum scale factor of 14 enables a theoretical window size of 1 Gigabyte (65,535 × 2^14 = 1,073,725,440 bytes), allowing even 400Gbps links to be fully saturated across intercontinental distances.
Linux Kernel Socket Buffer Tuning (`/etc/sysctl.conf`)
While modern Linux kernels enable window scaling by default (`net.ipv4.tcp_window_scaling = 1`), the maximum auto-tuning socket buffer sizes (`rmem_max` and `wmem_max`) are often left at conservative legacy defaults (e.g., 212 KB or 4 MB). For multi-gigabit WAN servers, deploy the production parameters below:
# Enable RFC 7323 TCP Window Scaling & Selective Acknowledgments (SACK) net.ipv4.tcp_window_scaling = 1 net.ipv4.tcp_sack = 1 net.ipv4.tcp_timestamps = 1 # Maximum socket receive and send buffer sizes across all protocols (128MB) net.core.rmem_max = 134217728 net.core.wmem_max = 134217728 # Default socket receive and send buffer sizes (16MB) net.core.rmem_default = 16777216 net.core.wmem_default = 16777216 # Memory limits for TCP buffers: min, default, max (Bytes) # Max set to 128MB to accommodate BDP for 10Gbps across up to 100ms RTT net.ipv4.tcp_rmem = 4096 87380 134217728 net.ipv4.tcp_wmem = 4096 65536 134217728 # Maximum number of packets queued on the input side if interface receives packets faster than kernel can process net.core.netdev_max_backlog = 250000 # Enable TCP BBR Congestion Control (Kernel 4.9+) net.core.default_qdisc = fq net.ipv4.tcp_congestion_control = bbr
Congestion Control: CUBIC vs BBRv3
Socket buffers define capacity; the congestion control algorithm determines how aggressively TCP fills that capacity and how it responds to drops:
WAN Congestion Control Evaluation Matrix
| Congestion Algorithm | Operational Basis | Loss Handling (1% Loss) | Bufferbloat Behavior | 10G+ WAN Verdict |
|---|---|---|---|---|
| BBRv3 (Bottleneck Bandwidth & RTT) | Explicit model of max delivery rate and min RTT | Robust: sustains line rate despite 5–15% random packet drops | Minimal: bounds queue build-up at bottleneck switch | Exceptional |
| CUBIC (Default Linux Kernel) | Cubic window growth function independent of RTT | Collapses congestion window by 30% on single drop | High: aggressively fills buffers until packet tail-drop occurs | Suitable |
| TCP Westwood+ | Bandwidth estimation via ACK arrival rate intervals | Moderate: faster window recovery over lossy wireless/microwave | Moderate: relies on loss signals to trigger backoff | Limited |
| Reno / NewReno (Legacy AIMD) | Linear window increase (+1 MSS/RTT), multiplicative halve (-50%) | Catastrophic: cuts window by 50% per dropped packet event | Severe: creates deep queue latency before recovery | Not Recommended |
CUBIC treats any packet drop as an indicator of network congestion. On carrier WAN circuits that traverse multiple hops or alt-net peering fabrics, transient micro-burst drops cause CUBIC to throttle its transmission window by 30%, causing a saw-tooth throughput pattern that rarely achieves line rate.
BBR (Bottleneck Bandwidth and RTT), developed by Google, decouples congestion control from packet loss. By continuously measuring delivery rate and round-trip time, BBR operates at the exact network capacity without over-filling intermediary router buffers, making it the preferred algorithm for high-BDP WAN interconnects and backup replications.
MTU Overhead: Jumbo Frames vs Encapsulation
Payload throughput is further bounded by packet processing rates. On a 10Gbps link, standard 1,500-byte MTU packets require the NIC and CPU to process approximately 812,000 packets per second (pps).
Deploying end-to-end 9,000-byte Jumbo Frames reduces the interrupt rate to ~138,000 pps, significantly lowering CPU utilization and increasing single-stream throughput by 3–5%.