HomeArticlesNetworks & Distributed Systems

TCP Congestion Control: Slow Start, AIMD & the Cwnd Sawtooth

TCP has no idea how fast your network connection is. It finds out by probing — growing its congestion window until packets start dropping, then backing off. That feedback loop is why the internet doesn't collapse under load.

mysimulator teamUpdated July 2026≈ 7 min read▶ Open the simulation

The congestion window: TCP's speed dial

TCP sends multiple segments without waiting for each individual acknowledgement, and the congestion window (cwnd) is what limits how many bytes can be in flight at once. Throughput follows directly: throughput ≈ cwnd / RTT. Push cwnd too high for the network's actual capacity and a bottleneck buffer fills and starts dropping packets; keep it too low and you leave bandwidth unused. TCP has no direct way to measure available bandwidth, so classic algorithms treat packet loss itself as the signal that cwnd has grown too large.

Slow start: exponential probing

A new connection starts in slow start, where cwnd doubles every round-trip time — exponential growth, despite the name, chosen because a brand-new connection has no idea what the path can support and needs to ramp up quickly rather than crawl. Once cwnd crosses a threshold (or a loss occurs), TCP switches to congestion avoidance, where cwnd grows only linearly, adding roughly one segment per round-trip — a far more cautious probe for any remaining spare capacity.

live demo · the cwnd sawtooth and a bottleneck buffer filling● LIVE

AIMD and the sawtooth

Once in congestion avoidance, classic TCP variants apply Additive Increase, Multiplicative Decrease (AIMD): grow cwnd by roughly one segment per round-trip, and the instant a loss is detected, cut it sharply — Reno halves cwnd, while older Tahoe drops all the way back to 1 segment and restarts slow start entirely. Plotted over time, Reno's repeated slow linear climb followed by a sudden halving traces the well-known sawtooth pattern, a visual signature of a TCP flow continuously testing the edge of available capacity and backing off when it finds it.

Slow start:           cwnd(t+RTT) = 2 · cwnd(t)          (until threshold or loss)
Congestion avoidance: cwnd(t+RTT) = cwnd(t) + 1 MSS       (linear probing)
Loss detected (Reno): cwnd → cwnd / 2                      (multiplicative decrease)
Timeout (Tahoe):      cwnd → 1 MSS, restart slow start

Beyond loss-based control: CUBIC and BBR

Reno and Tahoe treat any packet loss as a congestion signal, which works poorly on modern high-bandwidth, high-delay links where a single loss event can needlessly halve a connection carrying gigabits per second. CUBIC, the Linux default since 2006, grows cwnd along a cubic function of time since the last loss, recovering capacity faster on long "elephant" flows. Google's BBR takes a different approach entirely, modelling the path's actual bottleneck bandwidth and round-trip time directly instead of reacting to loss after the fact — on high bandwidth-delay-product networks this can deliver 2-10× better throughput than loss-based algorithms, because it stops treating a full buffer as the only signal worth listening to.

Frequently asked questions

What is the congestion window and how does it control throughput?

The congestion window (cwnd) is the number of unacknowledged bytes TCP allows in flight at once. Throughput is approximately cwnd divided by round-trip time, so TCP controls speed by growing or shrinking cwnd based on whether packets are getting through or being lost.

What is the difference between slow start and congestion avoidance?

In slow start, cwnd doubles every round-trip time, growing exponentially until it hits a threshold or a loss occurs. In congestion avoidance, cwnd grows linearly instead, adding roughly one segment per round-trip, a much more cautious probe for extra capacity.

Why does TCP Reno's throughput graph look like a sawtooth?

Reno's AIMD (additive increase, multiplicative decrease) rule grows cwnd by one segment per round-trip until a loss is detected, then halves it instantly. That repeated slow climb followed by a sharp drop traces a sawtooth pattern on a plot of cwnd over time.

Try it live

Everything above runs in your browser — open TCP Congestion Control, switch between Tahoe, Reno and CUBIC, and watch the cwnd sawtooth trace out as a bottleneck buffer fills and drops packets.

▶ Open TCP Congestion Control simulation

What did you find?

Add reproduction steps (optional)