Receive Window vs Congestion Window
| Window | Who Controls It? | What It Protects |
|---|---|---|
| Receive window (rwnd) | Receiver | Receiver buffer space |
| Congestion window (cwnd) | Sender | The network path from overload |
| Effective send window | Both limits together | Sender can only send up to the smaller of the two |
The Sliding Window Mechanism
TCP uses a sliding window to allow continuous data flow without waiting for an acknowledgment after every single segment. The sender maintains a window of bytes that it is allowed to have outstanding (sent but not yet acknowledged). As acknowledgments arrive, the window slides forward and the sender can send more data. This keeps the pipe full rather than idle. The key constraint is that the sender must never have more than min(rwnd, cwnd) bytes outstanding at any moment.
The receive window (rwnd) is advertised by the receiver in every TCP segment it sends back. It tells the sender how much free buffer space the receiver currently has. If the receiver's application is slow to consume data from its buffer, rwnd shrinks. If the receiver sends a zero-window advertisement, the sender must stop entirely and probe periodically.
Bandwidth-Delay Product
The bandwidth-delay product (BDP) is the amount of data that needs to be in flight to keep a high-speed, high-latency path fully utilized. The formula is:
BDP = bandwidth × round-trip time
A 1 Gbps link with 5 ms RTT has a BDP of about 625 KB. A 1 Gbps link with 100 ms RTT has a BDP of about 12.5 MB. If the TCP window is smaller than the BDP, the sender runs out of permission to send before an acknowledgment returns, forcing it to stall. This is exactly why satellite internet connections — which have high bandwidth but 600 ms or more of RTT — can feel sluggish even with plenty of capacity.
Window Scaling: RFC 7323
The original TCP header encodes the receive window in a 16-bit field, capping it at 65,535 bytes. RFC 7323 (and its predecessor RFC 1323) introduced the window scale option, negotiated during the three-way handshake. Each side advertises a scale factor (0–14), and the actual window size is the header field value shifted left by that factor. A scale factor of 7 means the effective window is the 16-bit value multiplied by 128, allowing windows up to 230 bytes (about 1 GB). Both endpoints must advertise the option during the handshake for scaling to be active on that connection. If a middlebox strips the SYN options, scaling will not be negotiated, and both sides silently cap the window at 65,535 bytes — a common cause of poor throughput on fast long-distance paths.
Effect on Speed Test Results at High Latency
When you run a speed test to a distant server, TCP window size directly limits the achievable throughput. With a 20 ms RTT and a 65,535-byte window, the theoretical maximum is about 26 Mbps regardless of your link capacity. With window scaling and a 4 MB window, the same 20 ms RTT allows up to about 1.6 Gbps. Speed test tools that use a single TCP stream from a distant server may measure well below your actual line capacity simply because the TCP window cannot grow fast enough during the test duration. Tools that use multiple parallel streams or that measure on nearby servers circumvent this.
TCP Receive Buffer Tuning
On Linux, the kernel auto-tunes socket receive buffers within bounds set by net.ipv4.tcp_rmem (minimum, default, maximum). The default maximum is typically 4–16 MB on modern kernels, which is sufficient for most paths. On high-BDP paths, administrators sometimes raise net.core.rmem_max and the tcp_rmem maximum to 32 MB or more. On Windows, TCP auto-tuning has been the default since Vista; it is controlled by the netsh interface tcp set global autotuninglevel setting and should generally be left on Normal. Disabling auto-tuning or setting it to Disabled is a common legacy suggestion that typically makes things worse on modern links.
| OS | Key Setting | Typical Default Max | Notes |
|---|---|---|---|
| Linux | net.ipv4.tcp_rmem (third value) | 4–16 MB | Auto-tuning adjusts within this range |
| Linux | net.core.rmem_max | 212992 bytes | Hard ceiling for socket buffers |
| Windows | TCP auto-tuning level | Normal | Should not be disabled on modern systems |
| macOS | net.inet.tcp.recvspace | 131072 bytes | Kernel auto-scales beyond this for fast links |
Analyzing Window Size in Wireshark
Wireshark makes TCP window behavior visible. The Calculated window size column (after accounting for the scale factor) shows the effective rwnd. The TCP Stream Graph → Window Scaling graph shows how rwnd changes over time. A graph that stays flat at 65,535 bytes on a fast connection usually means window scaling was not negotiated — often because a middlebox stripped the options from the SYN. A graph where rwnd repeatedly drops toward zero indicates the receiver's buffer is filling faster than the application drains it, pointing to an application or CPU bottleneck rather than a network issue.
What Can Still Limit Throughput
- The receiver advertises a small receive window that it does not grow.
- The sender's congestion window is reduced after packet loss and has not recovered.
- A middlebox strips or modifies TCP options including window scaling during the handshake.
- High latency multiplies the effect of a limited window, making each stall last longer.
- The application reads or writes data slowly, starving the socket buffer.
- Bufferbloat causes high RTT variation that confuses congestion algorithms.
What Users Should Actually Do
Modern operating systems auto-tune TCP buffers and window sizes. Manually adjusting old registry or sysctl settings is rarely the right first step. Investigate packet loss, bufferbloat, VPN overhead, bad Wi-Fi signal, overloaded servers, or middlebox interference before assuming the TCP window needs manual tuning. If throughput to a nearby server is good but a distant server is slow, the window size or RTT interaction is a plausible cause worth investigating with Wireshark or a tool like iperf3.
Frequently Asked Questions
What is TCP window size?
TCP window size usually refers to the receive window, which tells the sender how much data the receiver can accept before more acknowledgments are needed.
What is TCP window scaling?
TCP window scaling is an option that allows receive windows larger than the original 16-bit TCP window field, which is important for high-bandwidth high-latency paths.
Can TCP window size limit speed?
Yes. If the usable TCP window is too small for the bandwidth-delay product of a path, the sender cannot keep enough data in flight to fill the connection.