Flow control prevents a fast sender from overwhelming a slow receiver. TCP uses a receive window (rwnd) advertised by the receiver to limit in-flight data. If the receiver's buffer fills, it shrinks rwnd to zero, pausing the sender until the application drains the buffer.
Flow control is an end-to-end mechanism between sender and receiver – distinct from congestion control which manages network-wide traffic. TCP's receive window (rwnd) tells the sender how much buffer space the receiver has available. The sender never has more unacknowledged bytes in flight than min(cwnd, rwnd). When a receiver's application reads slowly, the receive buffer fills, rwnd shrinks toward zero, and the sender pauses – this is called zero-window. The sender periodically sends window probe packets to detect when rwnd opens again. HTTP/2 adds its own flow control at the stream level via WINDOW_UPDATE frames – preventing one slow stream from blocking others sharing the connection. QUIC similarly has per-stream and connection-level flow control independent of the underlying UDP transport.
Congestion
Network congestion occurs when traffic exceeds link or buffer capacity, causing packet loss and increased latency. TCP congestion control algorithms (Cubic, BBR, Reno) dynamically adjust sending rate to avoid overwhelming the network. Persistent congestion degrades all traffic on the shared path.
Sliding Window
The sliding window is TCP's mechanism for sending multiple packets before requiring acknowledgment. The window size determines how much data can be in-flight simultaneously. Without windowing, the sender waits for each ACK before sending the next segment – wasting bandwidth on high-latency links.