TCP window size is the amount of data, in bytes, that a TCP sender is allowed to have in flight without acknowledgment before it must stop and wait. Among transport protocols, it is the core mechanism of flow control in TCP: the receiver advertises a receive window (rwnd) that reflects its free buffer space, and the sender never exceeds it.
The usable window also depends on the sender’s congestion window (cwnd), so the effective limit is the smaller of rwnd and cwnd. Because throughput on a single connection can never exceed the window divided by the round-trip time, window size directly decides how fast TCP can move data across long or fast networks.
How the sliding window works
TCP numbers every byte it sends. Each acknowledgment from the receiver confirms bytes up to a sequence number and carries a 16-bit window field that states how many further bytes the receiver can accept. The sender may transmit any byte that falls inside this sliding window, which moves forward as acknowledgments arrive.
When an application on the receiving side reads data slowly, its socket buffer fills, the advertised window shrinks and the sender slows down. If the buffer fills completely, the receiver advertises a zero window and the sender stops, periodically sending window probes until space reopens. This keeps a fast sender from overwhelming a slow receiver.
The window is distinct from segment size. The MSS limits how much data fits into one segment, typically 1,460 bytes on standard Ethernet with a 1,500-byte MTU, while the window limits how many such segments may be outstanding at once.
Window scaling and the bandwidth-delay product
The original header field allows a maximum window of 65,535 bytes, which became a bottleneck once networks grew faster. The window scale option defined in RFC 7323 multiplies the advertised value by a power of two, negotiated during the TCP handshake, with a shift count of up to 14. This raises the maximum window to about 1 GiB.
The window needed for full speed equals the bandwidth-delay product (BDP): link bandwidth multiplied by round-trip time. The table below shows how quickly the required window grows on fast or distant paths.
| Bandwidth | Round-trip time | Required window | Without scaling |
|---|---|---|---|
| 100 Mbit/s | 10 ms | About 125 KB | Limited to about 52 Mbit/s |
| 1 Gbit/s | 20 ms | About 2.5 MB | Limited to about 26 Mbit/s |
| 1 Gbit/s | 100 ms | About 12.5 MB | Limited to about 5 Mbit/s |
| 10 Gbit/s | 50 ms | About 62.5 MB | Limited to about 10 Mbit/s |
The ceiling follows from a simple formula: maximum throughput = window / RTT. A 64 KB window over a 100 ms path yields at most about 5 Mbit/s regardless of link capacity, which explains why transfers between continents can be slow on connections that perform well locally.
Receive window versus congestion window
Two different windows constrain a sender, and confusing them is a common source of tuning errors. The comparison below separates their roles.
| Property | Receive window (rwnd) | Congestion window (cwnd) |
|---|---|---|
| Controlled by | Receiver | Sender |
| Purpose | Flow control, protects the receiver | Congestion control, protects the network |
| Visible on the wire | Yes, in every TCP header | No, internal sender state |
| Driven by | Free socket buffer space | Loss, delay and the congestion algorithm |
| Typical growth | Auto-tuned by the operating system | Slow start, then algorithm-specific |
TCP congestion control algorithms such as CUBIC or BBR shape cwnd, starting from an initial window of about 10 segments on modern systems. A large receive window does not help when packet loss keeps cwnd small, and a well-behaved congestion window cannot help when the receiver advertises a small rwnd.
Tuning window size in practice
Modern operating systems use receive window auto-tuning, growing socket buffers as a connection shows a high BDP. Manual tuning is now mostly limited to high-throughput, high-latency paths such as data replication between distant data centers or scientific transfers.
| Platform | Mechanism | Typical setting |
|---|---|---|
| Linux | tcp_rmem and tcp_wmem sysctls | Maximum raised to tens of MB for long paths |
| Windows | Receive window auto-tuning level | Normal level, which permits scaling |
| Applications | SO_RCVBUF and SO_SNDBUF socket options | Fixed buffers, which can disable auto-tuning |
| Measurement tools | Window option in iPerf and similar tools | Set to at least the path BDP |
A frequent mistake is setting a fixed socket buffer in an application, which on Linux turns off auto-tuning for that socket and can lock the window to a value far below the BDP. Another is assuming that a larger buffer is always better: oversized buffers on congested links contribute to bufferbloat, raising latency for other traffic.
Diagnosing window problems
Window limits show up as throughput that plateaus well below link capacity while the path shows little packet loss. Packet captures make the cause visible, because analyzers track the advertised window over time and flag specific events.
- Zero window events mean the receiving application is not reading data fast enough.
- Window full events mean the sender has used the entire advertised window and is waiting.
- Missing window scale option in the handshake, often caused by an old middlebox, caps the window at 64 KB.
- Throughput equal to window divided by RTT across many tests points to a window limit rather than a capacity limit.
Because the scale factor is negotiated only once, captures that miss the handshake show unscaled raw values, so analysis should start from the SYN packets whenever possible.
The simple explanation
When one computer sends data to another over TCP, it cannot send everything at once. The receiver says how much it can take right now. That amount is the window. The sender sends up to that amount, then waits for a confirmation before sending more.
Picture a conveyor belt between two workers. The second worker says how many boxes fit on the table. If the table is small and the belt is long, the first worker spends most of the time waiting. A bigger window keeps the belt full, which matters most when the distance is long.
How it is used in practice
A company replicates nightly database backups from Europe to a disaster recovery site in North America over a dedicated 1 Gbit/s circuit with a round-trip time of about 90 ms. The transfer runs at only about 45 Mbit/s and does not finish before the morning.
A packet capture shows that the backup software sets a fixed 512 KB receive buffer, and window full events appear constantly. With a BDP of roughly 11 MB, the window allows only a small fraction of the circuit. The engineers remove the fixed buffer setting and raise the Linux tcp_rmem maximum to 32 MB. Throughput rises to about 900 Mbit/s, and the nightly job completes in well under an hour.