Skip to content
UniCircle
HardConceptualTransport layer

TCP congestion control: slow start, AIMD and fast recovery

Question NET-109

Explain how TCP congestion control works. Cover slow start, congestion avoidance, and how TCP reacts differently to a timeout versus three duplicate ACKs. How is congestion control different from flow control?

Show hints

Track two variables: the congestion window (cwnd) and the slow-start threshold (ssthresh).

Show the explanation

Model answer. Congestion control stops senders from overwhelming the network. The sender keeps a congestion window (cwnd); the amount of unacknowledged data in flight is limited to min(cwnd, receiver's advertised window). The classic algorithm (TCP Reno) works as follows.

Slow start

  • A new connection starts with a small cwnd (classically 1 MSS; modern stacks commonly use 10 segments per RFC 6928).
  • cwnd grows by 1 MSS for every ACK received, so it roughly doubles every round-trip time — exponential growth, despite the name.
  • This continues until cwnd reaches the slow-start threshold (ssthresh) or loss occurs.

Congestion avoidance (additive increase)

  • Above ssthresh, cwnd grows by about 1 MSS per RTT — linear probing for spare capacity.

Reaction to loss (multiplicative decrease)

  • Three duplicate ACKs: the receiver is still getting later segments, so the network is only mildly congested. TCP does fast retransmit of the missing segment without waiting for a timeout, sets ssthresh = cwnd / 2, and with fast recovery continues from about the halved window (Reno sets cwnd = ssthresh + 3 MSS during recovery, then ssthresh once new data is acknowledged) instead of restarting slow start.
  • Retransmission timeout (RTO): nothing is getting through, a sign of severe congestion. TCP sets ssthresh = cwnd / 2, resets cwnd to 1 MSS, and re-enters slow start.

This "additive increase, multiplicative decrease" (AIMD) gives the familiar sawtooth cwnd graph and moves competing flows towards a fair share.

Congestion control vs flow control

  • Flow control protects the receiver: the receiver advertises its free buffer space in the TCP window field (rwnd), and the sender never exceeds it.
  • Congestion control protects the network: cwnd is the sender's own estimate of what the path can carry; it is never sent in a header.

Modern variants: CUBIC (Linux default) grows cwnd as a cubic function of time since the last loss; BBR models bottleneck bandwidth and RTT instead of relying mainly on loss.

Follow-up: "Why is loss a poor congestion signal on Wi-Fi?" Radio errors cause losses too, so loss-based TCP slows down unnecessarily.

Original UniCircle question. Last reviewed 28 Oct 2026.