arthrop0d

Brief articles on varied topics.

TCP Slow Start and Congestion Avoidance

networking

TCP slow start is the phase in which a TCP sender cautiously discovers how much data the network can carry. It grows the congestion window, or cwnd, quickly at first, then changes to congestion avoidance when packet loss suggests that the sender is approaching or exceeding the path’s capacity.

The result is not a fixed sending speed. TCP continually adjusts how much unacknowledged data may be in flight.

The problem TCP is solving

A sender usually does not know the capacity of the path between it and the receiver. The path may include links with different speeds and routers with finite queues. Sending at the sender’s local maximum can fill those queues, causing delay and dropped packets.

Before congestion control, a fast sender could inject data faster than the network could forward it. Queues would grow until packets were discarded, and retransmissions could add even more traffic. This feedback loop is called congestion collapse: more sending produces less useful throughput.

TCP therefore probes for available capacity. It starts conservatively, observes acknowledgements, and increases its sending allowance while the network appears to cope.

The sender is not asking, “How fast is my application producing data?” It is asking, “How much unacknowledged data can this path currently carry?”

The congestion window

cwnd is a limit, maintained by the sender, on the amount of data that may be outstanding: sent but not yet acknowledged. TCP also has a receive window, or rwnd, advertised by the receiver to prevent the sender from overrunning the receiver’s buffer.

The sender’s usable flight size is bounded by both:

bytes in flight <= min(cwnd, rwnd)

This article focuses on cwnd. It is a property of the sender’s view of the network, not a buffer in a router and not a setting that directly controls the application’s write calls.

TCP usually describes window growth in MSS, the maximum segment size: the amount of TCP payload normally carried in one packet. Thinking in MSS-sized segments makes the algorithm easier to see.

Slow start: acknowledgements drive growth

At the beginning of a connection, TCP sets cwnd to a small initial value. The exact initial value depends on the TCP implementation and standards in use, but the important property is that it is limited.

As the sender transmits, the receiver returns ACKs, or acknowledgements. An ACK says which sequence number the receiver expects next, indirectly confirming that earlier bytes arrived in order. Each ACK gives the sender evidence that some data reached the receiver and that the path is making progress.

During slow start, the sender increases cwnd by approximately one MSS for each ACK that covers new data:

for each ACK of new data:
    cwnd += 1 MSS

Suppose cwnd allows four segments in flight. The sender sends four. If four ACKs arrive, the window grows by roughly four MSS, allowing about eight segments in the next round-trip time. Those eight acknowledgements can grow it to about sixteen, and so on.

That is why slow start is approximately exponential per round-trip time, even though the increase is made one ACK at a time. Each acknowledged segment creates room for another segment, so a whole flight’s worth of ACKs can roughly double the next flight.

“Slow start” is therefore slow only compared with immediately sending at line rate. Its growth can become very fast on a high-bandwidth path.

Delayed acknowledgements slightly change the exact arithmetic: a receiver may acknowledge every second full-sized segment rather than every segment. TCP implementations also apply safeguards against unusually large or misleading ACKs. The useful mental model remains that successful delivery generates ACKs, and ACKs let the sender expand cwnd.

The threshold and congestion avoidance

TCP maintains another value, commonly called ssthresh, or the slow-start threshold. While cwnd is below that threshold, TCP uses slow start. Once cwnd reaches the threshold, it changes to congestion avoidance.

Congestion avoidance grows much more slowly. Its traditional behavior is approximately additive increase: increase the window by about one MSS per round-trip time rather than doubling it every round trip. A per-ACK version of that rule is commonly expressed as:

for each ACK of new data:
    cwnd += MSS * MSS / cwnd

If the window is large, each ACK adds only a small fraction of an MSS. After enough ACKs arrive to account for one full window of data, the total increase is about one MSS. The window therefore climbs gradually, allowing TCP to probe for extra capacity without rapidly overfilling queues.

The transition at ssthresh is not a claim that the network has exactly reached a known limit. It is a practical change from aggressive discovery to cautious probing, based on what TCP has learned so far.

What packet loss changes

TCP treats packet loss as evidence that the path may be congested. A dropped packet can have other causes, such as corruption or a broken link, but classic TCP congestion control generally cannot distinguish those cases reliably. It responds as though the network’s queues may have overflowed.

Loss can be detected by a retransmission timeout, meaning the expected ACK did not arrive before TCP’s timer expired. It can also be inferred from duplicate ACKs: later data arrived, but the receiver kept acknowledging the same missing sequence range. Several duplicate ACKs typically trigger fast retransmission before the timer expires.

On loss, TCP reduces its sending allowance and sets a new slow-start threshold, often based on the previous cwnd. The exact response depends on the TCP congestion-control algorithm and the loss signal:

The specific numbers vary across modern algorithms, but the principle is stable: successful ACKs permit growth; loss causes a reduction; subsequent growth becomes cautious.

This is the behavior behind log messages and metrics such as cwnd, ssthresh, retransmissions, duplicate ACKs, and TCP slow start. If an incident report says a connection repeatedly leaves slow start, loses packets, cuts its window, and grows again, it is describing TCP’s feedback loop for finding a rate the network can sustain.

← All articles