Explain slow start and congestion avoidance. What is ssthresh?
Show the answer
Say this first
A new connection does not know the path's capacity, so it starts with a small congestion window, 10 segments on modern stacks. In slow start cwnd grows by one segment per ACK, which doubles it every round trip. When cwnd reaches ssthresh, TCP switches to congestion avoidance and grows by about one segment per round trip. On loss detected by duplicate ACKs, ssthresh is set to about half the data in flight and cwnd drops to it. On a timeout, cwnd goes back to one segment and slow start begins again. ssthresh is the line between the two phases.
Go deeper
Round by round
| RTT | Phase | cwnd (segments) |
|---|---|---|
| 1 | Slow start | 10 |
| 2 | Slow start | 20 |
| 3 | Slow start | 40 |
| 4 | Slow start | 80, loss detected |
| 5 | Recovery | ssthresh = 40, cwnd = 40 |
| 6 | Congestion avoidance | 41 |
| 7 | Congestion avoidance | 42 |
This additive increase and multiplicative decrease (AIMD) makes the familiar sawtooth.
Why the initial window matters
An initial window of 10 segments (RFC 6928) is about 14.6 KB. A small web response fits in the first flight; a large one needs several round trips of slow start, which is why latency, not bandwidth, dominates small transfers.
Slow start after idle
Linux shrinks cwnd back toward the initial window when a connection has been idle for longer than one
RTO (net.ipv4.tcp_slow_start_after_idle=1). Long-lived connections that send in bursts, like HTTP/2 or
database links, sometimes turn it off.
They will ask next
Why is it called slow start if it grows exponentially?
It is slow compared with what came before it: early TCP sent a whole receive window at once and caused congestion collapse. Starting small and doubling was the slow, careful option.
Where does ssthresh start?
Very high, effectively unlimited, so the first slow start runs until the first loss or until the receive window caps it. Linux can cache metrics per destination, including ssthresh, between connections.
Traps
- Saying cwnd starts at one segment on modern systems. Linux and most stacks start at 10.