# How TCP/IP Dynamic Window Scaling and Selective Acknowledgment Optimize Throughput in High‑Latency Networks

> Learn how TCP/IP dynamic window scaling and SACK optimize throughput in high-latency networks by removing the 65KB limit and enabling precise retransmissions.

- Repository: [Arie Bregman/devops-exercises](https://github.com/bregman-arie/devops-exercises)
- Tags: performance
- Published: 2026-02-28

---

**TCP/IP dynamic window scaling and selective acknowledgment (SACK) work together to eliminate the 65 KB receive‑window ceiling and enable precise retransmission of only lost segments, allowing the protocol to sustain near‑line‑rate throughput on high‑latency links.**

In the `bregman-arie/devops-exercises` repository, the Linux networking and TCP/IP fundamentals sections provide practical commands and conceptual context for these optimizations. When round‑trip times (RTT) stretch into hundreds of milliseconds—as seen in satellite or trans‑continental WAN links—standard TCP flow control becomes a bottleneck. Dynamic window scaling and SACK are the two primary mechanisms that remove this limitation while maintaining reliability.

## The Bandwidth‑Delay Product Limitation

Traditional TCP headers use a 16‑bit field to advertise the receive window, capping the in‑flight data limit at **65 KB**. On high‑bandwidth, high‑latency paths, this ceiling falls far below the **Bandwidth‑Delay Product (BDP)**—the amount of data that can be "in flight" to keep the pipe full. When the BDP exceeds 65 KB, the sender stalls waiting for acknowledgments, leaving bandwidth underutilized. According to the repository’s overview of TCP fundamentals in [`README.md`](https://github.com/bregman-arie/devops-exercises/blob/main/README.md), this constraint is why modern extensions are essential for WAN performance.

## Dynamic Window Scaling (RFC 7323)

### Overcoming the 16‑Bit Window Limit

RFC 7323 introduces a **4‑bit scale factor** (0–14) that is negotiated during the three‑way handshake. The effective receive window becomes `rcv_win << scale`, theoretically permitting windows up to approximately **1 GB**. This scaling allows the sender to push enough segments into the network to saturate the link even when RTTs are large.

### Handshake Negotiation

As documented in the repository’s *What is TCP?* and *3‑way handshake* sections of [`README.md`](https://github.com/bregman-arie/devops-exercises/blob/main/README.md), both endpoints must announce the `WS` (window‑scale) option during SYN/SYN‑ACK exchange. Without this negotiation, the connection falls back to the legacy 16‑bit limit regardless of OS settings.

## Selective Acknowledgment (RFC 2018 / RFC 6675)

### Precise Loss Recovery vs. Cumulative ACKs

Without SACK, TCP acknowledgments are cumulative: a duplicate ACK only indicates the next expected byte, forcing the sender to assume all subsequent data is lost. This triggers unnecessary retransmissions and aggressive congestion‑window reductions. **Selective Acknowledgment** allows the receiver to advertise specific blocks of successfully received data beyond the first gap using TCP option fields.

### Preserving Throughput During Recovery

On high‑latency links, retransmitting only the missing segments—rather than the entire window—drastically reduces recovery time. The sender uses SACK information to perform **Fast Retransmit/Fast Recovery** without collapsing the congestion window, preserving the large send window built by dynamic scaling.

## How Window Scaling and SACK Work Together

1. **Handshake Phase:** Both ends exchange `WS` and `SACK‑Permitted` options, enabling the features for the session.
2. **Data Transfer:** The receiver advertises a scaled window (`rcv_wnd << scale`), allowing the sender to maintain a flight size equal to the BDP.
3. **Loss Detection:** When a segment drops, the receiver continues acknowledging out‑of‑order blocks via SACK options in subsequent ACKs.
4. **Fast Recovery:** The sender retransmits only the gaps indicated by SACK blocks, avoiding a full window reduction and maintaining high throughput.

## Configuring and Monitoring on Linux

The [`topics/linux/README.md`](https://github.com/bregman-arie/devops-exercises/blob/main/topics/linux/README.md) file in the repository recommends using `sar -n TCP,ETCP 1` to monitor TCP statistics, including retransmission rates and window utilization. You can verify and tune these features using `sysctl`:

```bash

# Enable window scaling and SACK (usually default on modern kernels)

sudo sysctl -w net.ipv4.tcp_window_scaling=1
sudo sysctl -w net.ipv4.tcp_sack=1

# Verify current settings

sysctl net.ipv4.tcp_window_scaling net.ipv4.tcp_sack

```

To inspect the effective window size on active connections:

```bash

# Display scaled receive window values

ss -ti | grep -i rcv_wnd

```

### Python Socket Configuration

When building high‑throughput applications, you can ensure these features are utilized at the socket level:

```python
import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Ensure window scaling is not clamped (0 = no limit)

s.setsockopt(socket.IPPROTO_TCP, socket.TCP_WINDOW_CLAMP, 0)

# Explicitly enable SACK (usually already enabled by default)

s.setsockopt(socket.IPPROTO_TCP, socket.TCP_SACK, 1)

s.connect(('example.com', 80))
s.sendall(b'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n')
print(s.recv(4096))
s.close()

```

## Summary

- **Dynamic window scaling** (RFC 7323) removes the 65 KB window limit using a negotiated scale factor, enabling windows up to ~1 GB to match high BDP links.
- **Selective Acknowledgment** (RFC 2018) allows receivers to report specific received blocks, enabling senders to retransmit only lost segments rather than entire windows.
- Together, they maintain a large congestion window and minimize recovery time after loss, which is critical for high‑latency networks.
- In `bregman-arie/devops-exercises`, practical monitoring commands like `sar -n TCP,ETCP` and `ss -ti` demonstrate how to verify these features are active.

## Frequently Asked Questions

### What is the maximum window size with TCP window scaling?

With the 4‑bit scale factor (0–14) defined in RFC 7323, the theoretical maximum receive window is approximately **1 GB** (65,535 bytes × 2^14). This allows TCP to support bandwidth‑delay products far exceeding the original 65 KB limit, essential for high‑speed satellite or inter‑continental links.

### How does selective acknowledgment differ from traditional cumulative ACKs?

Traditional cumulative ACKs only confirm the last contiguous byte received; any gap forces the sender to retransmit everything from the gap onward. **Selective Acknowledgment** uses TCP options to list specific blocks of received data, allowing the sender to identify and retransmit **only** the missing segments, reducing recovery time and preserving throughput.

### Can I disable window scaling or SACK, and should I?

While you can disable these features via `sysctl` (`net.ipv4.tcp_window_scaling=0` or `net.ipv4.tcp_sack=0`), doing so is **not recommended** for production systems. Disabling window scaling caps throughput on high‑latency links, and disabling SACK increases retransmission overhead and slows loss recovery. Modern OS kernels enable both by default for optimal performance.

### How can I verify that window scaling is active on a specific connection?

On Linux, use the `ss -ti` command to inspect active TCP sockets. Look for the `rcv_wnd` value in the output; if window scaling is active, the displayed value reflects the scaled window size (often much larger than 65,535 bytes). The repository’s [`topics/linux/README.md`](https://github.com/bregman-arie/devops-exercises/blob/main/topics/linux/README.md) notes that `sar -n TCP,ETCP` can also track segment retransmissions, indirectly indicating whether the window is large enough to keep the pipe full.