TCP window size and window scaling: why fast links can still feel slow
In short: TCP can only have one receive window of unacknowledged data in flight, so throughput is limited to window size divided by round-trip time. The original 16-bit field caps the window at 65,535 bytes, too small for fast, long-distance links. The window scale option, agreed in the handshake, multiplies the field by up to 2^14 so windows can reach about 1 GB.
What the window does
TCP is reliable because the receiver acknowledges the data it gets. If the sender waited for an acknowledgement after every segment, it would spend most of its time idle. Instead, the receiver advertises a receive window: the number of bytes it is prepared to accept beyond what it has already acknowledged, based on free buffer space. The sender may have that many unacknowledged bytes in flight. As acknowledgements arrive, the window "slides" forward, which is why this is called a sliding window.
The window is flow control: it protects the receiver from being flooded. A busy receiver can shrink its window, and a window of zero tells the sender to pause until space frees up. Congestion control, which protects the network, is a separate mechanism; see TCP in depth.
The 64 KB ceiling and the bandwidth-delay product
The window field in the TCP header is 16 bits, so on its own it can advertise at most 65,535 bytes. On a LAN with a round-trip time (RTT) of under a millisecond, that is plenty. Over distance it is not, because a sender can push at most one window per round trip:
Rule: maximum throughput of one connection = window size / RTT.
With a 65,535-byte window and a 50 ms RTT, one connection cannot exceed about 65,535 × 8 / 0.05 ≈ 10.5 Mbit/s, even on a 1 Gbit/s link. To keep a link full, the window must be at least the bandwidth-delay product (BDP): the link speed multiplied by the RTT. For 1 Gbit/s and 40 ms, BDP = 1,000,000,000 × 0.04 = 40,000,000 bits, or 5 MB. That is about 76 times more than the field alone can express. Try other values with the bandwidth calculator.
How window scaling works
The window scale option, now defined in RFC 7323, solves this without changing the header. During the three-way handshake each side may include the option in its SYN with a shift count from 0 to 14. From then on, the real window is the 16-bit field value multiplied by 2shift (shifted left by that many bits). Key points:
- The option only appears in SYN segments. If either side leaves it out, scaling is off in both directions for that connection.
- Each direction has its own shift count, so the two sides can use different values.
- The largest shift is 14, giving a maximum window of just under 1 GB (230 bytes).
- Example: a window field of 2,000 with a shift of 7 means 2,000 × 128 = 256,000 bytes.
Modern operating systems enable scaling by default and also use receive window autotuning, growing the buffer as a connection proves it needs more.
Checking and troubleshooting
- Look at the handshake in a packet capture. If the capture starts mid-connection, the analyser cannot know the shift count and may show a misleadingly small window, so always capture from the SYN.
- Middleboxes: an old firewall, proxy or WAN optimiser that strips TCP options or rewrites windows can quietly disable scaling. Compare a capture on each side of the device.
- Zero windows: repeated zero-window messages mean the receiving application is not reading data fast enough, a server problem rather than a network one.
- Host settings can be checked with commands such as:
netsh interface tcp show global
sysctl net.ipv4.tcp_window_scaling
sysctl net.ipv4.tcp_rmem
The first is for Windows (look at Receive Window Auto-Tuning Level); the others are for Linux, where 1 means scaling is on.
Real-world example: slow replication to a distant data centre
A fictional engineering firm replicated design files every night from its office to a disaster recovery site about 70 ms away over a 500 Mbit/s link. Replication crawled at under 10 Mbit/s and often ran into the working day. The network team first suspected the provider, but the link tested fine with several parallel streams. A capture taken from the start of a replication session showed that the SYN from the office server carried a window scale option, while the SYN-ACK passing through an old firewall at the recovery site did not. The firewall's TCP normalisation feature was removing unknown options. After the setting was corrected, the shift count appeared on both sides, windows grew into megabytes and the nightly job finished in well under an hour.
Practice
What is the maximum throughput of one TCP connection with a 64 KB window and 100 ms RTT?
Calculate the bandwidth-delay product of a 100 Mbit/s link with 80 ms RTT.
A capture shows a window field of 1,024 and the handshake agreed a shift of 9. What is the real window?
Key takeaways
- The receive window limits how much unacknowledged data can be in flight.
- Throughput of one connection is at most window size divided by RTT.
- The window must be at least the bandwidth-delay product to fill a link.
- Window scaling is agreed in the SYNs: real window = field x 2^shift, shift 0 to 14.
- Capture from the handshake, and check middleboxes that may strip the option.
Original content written by Mohamed Fayas for FM TecHub. © 2026 FM TecHub. You're welcome to share a link to this page; please don't copy the text elsewhere without permission.