Map

TCP Congestion Control

Wiki conceptnetworkingtcpweb-performance โ†ณ show in map Markdown
title
TCP Congestion Control
type
concept
summary
How TCP throttles sending speed to prevent network collapse, and why the first RTT is ~13 kB
tags
networking, tcp, web-performance
created
2026-04-06
updated
2026-07-22

TCP's mechanism for preventing network collapse by throttling how fast a sender pushes data. Without it, packet loss causes retransmissions that cause more packet loss โ€” a feedback loop that took down the early internet in 1986.

How it works

The sender maintains a congestion window (cwnd): the number of unacknowledged packets allowed in flight. This indirectly caps throughput because it limits how much data can be sent per round trip.

Slow start governs new connections. The window starts at 10 packets (per RFC 6928) and doubles each RTT โ€” each ACK grows the window by one, and a full window's worth of ACKs arrives each round trip. Ten packets at typical ~1368-byte payloads means roughly 13 kB in the first RTT. See 13kb-tcp-slow-start for a worked example.

Congestion avoidance kicks in after the first sign of loss. The window grows linearly (+1 packet per RTT) instead of exponentially, probing for capacity without overshooting.

Slow start plus congestion avoidance is a feedback controller โ€” measure the error signal (loss), adjust the actuator (window size), repeat, and hope the loop settles instead of oscillating. Janert's feedback-control-for-computer-systems is the book that names the parts and gives the stability conditions, which is the thing you want the moment you write your own loop for an autoscaler or rate limiter.

Loss detection matters

How loss is detected changes the response:

  • Duplicate ACKs โ€” the receiver is still getting packets, just not the one it wanted. The window halves and congestion avoidance continues. This is "fast retransmit."
  • Timeout โ€” nothing came back. Maybe the network is still full of the sender's packets. The window resets to 1 and slow start runs again up to half the pre-loss window ("slow start threshold").

The distinction reflects uncertainty: duplicate ACKs mean data is flowing, timeout means it might not be.

Why it matters for the web

Because slow start limits the first RTT to ~13 kB, website performance depends heavily on what fits in that initial burst. Critical CSS and JavaScript should be inlined or kept small enough to arrive in the first flight. The often-cited "14.2 kB budget" is approximate โ€” actual sizes vary with MTU, VLANs, HTTP headers, TLS overhead, and compression.

TCP timer internals

TCP relies on internal kernel timers for connection lifecycle management โ€” not just congestion control but also TIME_WAIT expiration, retransmission timeouts, and keepalive probes. On macOS, these timers depend on a single uint32_t counter (tcp_now) that overflows after 49.7 days of uptime, freezing the TCP clock and breaking TIME_WAIT garbage collection. See macos-tcp-time-bomb for the full analysis.