Back to the map

Module 12 · Transport layer · Lesson 3 of 5

Congestion control

How millions of independent senders share the internet without collapsing it: the congestion window, slow start, additive increase and multiplicative decrease, CUBIC and BBR, bufferbloat.

DeepShould-knowSenior 14 minVideo Updated Nov 2026
Video walkthrough · 2:40 · narrated, with captions

Why it matters

In 1986 the early internet suffered congestion collapse: links stayed full, but almost all the traffic was retransmissions, and useful throughput fell a thousandfold. Congestion control was the fix, and it is still why the internet works. For engineers it explains everyday behaviour: why a new connection starts slowly, why a small response is dominated by round trips and a large one by bandwidth, why throughput halves after a loss, and why latency spikes when a link is busy.

The idea

The network gives senders no explicit signal of how much capacity is free. So each TCP sender keeps a congestion window (cwnd), its own estimate of how many bytes it can safely have in flight, probes for more capacity by growing it, and backs off sharply when it sees signs of congestion, classically packet loss. Each sender acts alone, yet together they converge on sharing the bottleneck roughly fairly. The effective window is the smaller of the congestion window and the receiver's advertised window.

The classic phases

  1. 1

    Slow start

    A new connection starts with a small window, typically 10 segments (about 14 KB), and doubles it every round trip while ACKs arrive: exponential growth to find capacity quickly.
  2. 2

    Congestion avoidance

    Past a threshold, growth becomes additive: about one segment per round trip, gently probing for more.
  3. 3

    Multiplicative decrease on loss

    On loss detected by duplicate ACKs, the window is cut (halved in classic Reno, by 30 percent in CUBIC) and growth resumes. On a retransmission timeout, the window collapses to one segment and slow start begins again.
cwndtime →slow start+1 per RTTloss: cutloss
The congestion window over time: exponential slow start, linear probing, a cut on each loss. The sawtooth is how a sender tracks the available capacity.

What this means in practice

A fresh connection with a 10-segment initial window can deliver about 14 KB in the first round trip, 28 KB in the second, 56 KB in the third. A 100 KB page therefore needs about four round trips just to ramp up, which on a 150 ms path is 600 ms regardless of bandwidth. That is why small responses are latency-bound, why keeping connections warm matters (an established connection has already grown its window), why CDNs terminate connections close to users, and why critical page resources are kept under the initial window.

Modern algorithms

AlgorithmSignalBehaviourWhere
Reno / NewRenoLossHalve on loss, grow one segment per RTT; slow to fill fast long linksHistorical baseline
CUBICLossWindow grows as a cubic function of time since the last loss, recovering quickly on high bandwidth-delay pathsLinux, Windows and macOS default
BBRMeasured bandwidth and minimum RTTModels the path's bottleneck bandwidth and round-trip time and paces sending to match, rather than filling buffers until lossGoogle services, many CDNs; opt-in on Linux
DCTCP and ECN-basedExplicit congestion marks from switchesReacts to marks before loss occurs, keeping queues shortData centres

Bufferbloat

Loss-based algorithms keep increasing the window until a buffer overflows. If routers and modems have very large buffers, they fill first, so packets queue for hundreds of milliseconds before any loss occurs: throughput is fine but latency for everyone on that link balloons. That is bufferbloat, felt when a video call lags while someone uploads a backup. Fixes are active queue management on routers (CoDel, FQ-CoDel), explicit congestion notification so routers can signal before dropping, and model-based algorithms like BBR that avoid filling queues.

Fairness and its limits

Congestion control shares a bottleneck roughly equally per connection, not per user or application. A client that opens ten parallel connections gets about ten shares, which is why browsers capped connections per host and why download accelerators were fast. Mixing algorithms (BBR flows beside CUBIC flows) can also share unequally. Rate limiting and traffic shaping at the application or network level exist because transport fairness is a convention, not an enforcement mechanism.

Trade-offs

Loss-based control is robust and simple, at the cost of underusing fast long links, misreading wireless loss as congestion, and filling buffers. Model-based control keeps latency low and fills fat pipes, at the cost of complexity and fairness questions. Slow start protects the network from new connections at the cost of latency for short transfers, which pushes systems toward connection reuse and edge termination.

In an interview

Use it to explain why proximity and reuse beat bandwidth: "A 200 KB response to Sydney over a cold connection takes about five round trips of slow start, roughly 800 ms, even on a gigabit link. Terminating TLS at an edge node near the user and keeping warm, already-ramped connections from edge to origin cuts that to one or two short round trips plus a fast backbone transfer."

Check yourself

A team doubles their servers' bandwidth from 1 to 2 Gbit/s, but the time to download a 60 KB API response to distant users on fresh connections does not improve. Why?

Congestion control · Backplane