TCP Congestion Control Explained

Why does internet speed swing up and down even on a stable connection? TCP is quietly negotiating with the network the whole time.

Why congestion control exists

The internet is a shared resource -- many connections pass through the same routers and links. If every sender pushed data as fast as possible, router buffers would overflow, causing a spike in packet loss and retransmissions that can collapse throughput for everyone. Congestion control is the mechanism TCP uses to throttle itself before that happens.

The congestion window (cwnd)

The congestion window is the amount of data a sender can put on the wire before waiting for acknowledgment. A larger window means higher throughput, but push it too far and the network can't keep up, causing loss. Nearly every congestion control algorithm boils down to a rule for growing and shrinking this one number.

Slow start: probing for capacity

A new connection starts with almost no information about the network, so TCP begins with a small window and doubles it every time acknowledgments arrive successfully. This exponential growth quickly finds a rough estimate of available capacity, until a loss event or a preset threshold ends slow start and hands off to the more cautious congestion-avoidance phase.

Congestion avoidance: back off on loss

Classic TCP treats packet loss as a signal that the network is congested. When loss is detected, the window is cut sharply (often by half), then grown slowly and linearly as long as no more loss occurs. Repeating this cut-and-grow cycle produces the characteristic sawtooth pattern seen in throughput graphs.

Reno and New Reno: the classic loss-based algorithms

TCP Reno, dating to the 1990s, combines slow start, congestion avoidance, and fast retransmit/fast recovery to react quickly to loss. New Reno improved recovery when multiple packets are lost in one window. Both struggle on very high-bandwidth links, where recovering slowly after a loss leaves a lot of capacity unused.

Cubic: Linux's default for high-bandwidth links

Cubic, the default algorithm in the Linux kernel, grows the window along a cubic (third-degree) curve over time. After a loss it recovers quickly toward the previous window size, then increases more cautiously near the point where the last loss occurred. This lets it use high-bandwidth, long-delay links far more efficiently than Reno-style algorithms.

BBR: measuring bandwidth and delay directly

Loss-based algorithms like Reno and Cubic only react once a router's buffer is already full -- a limitation tied to the bufferbloat problem. BBR, developed at Google, instead continuously estimates the real bottleneck bandwidth and the lowest recent round-trip time, aiming to hold the ideal sending rate before loss ever happens. It powers many of Google's own services and is available as an option in the Linux kernel.

Congestion control is just one part of TCP's reliability toolkit

Alongside congestion control, TCP relies on sequence numbers, acknowledgments, and retransmission timers to guarantee that data arrives complete and in order. Congestion control specifically addresses network-wide fairness and stability -- without it, a handful of aggressive senders could degrade a shared link for everyone else.

You can often see which algorithm you're using -- but rarely change it

Most consumer operating systems and browsers don't expose a control for switching congestion algorithms, since the setting is usually more consequential on servers than on client devices. Linux servers can typically list and switch available algorithms (such as Cubic or BBR) through kernel parameters, which is why the choice matters most for the operators of busy websites, video platforms, and CDNs.

Frequently Asked Questions

Can I switch which congestion control algorithm my device uses?

On Linux, yes -- the kernel exposes a setting to choose between algorithms like Cubic and BBR. Windows, macOS, and most mobile operating systems don't expose this to end users, and in practice the server side of a connection usually has more influence over perceived speed than the client side.

Does congestion control apply to video calls and game traffic sent over UDP?

UDP itself has no built-in congestion control, so a poorly-behaved UDP application can keep pushing data even when the network is congested, hurting everyone sharing that link. Modern protocols built on top of UDP, such as QUIC, implement their own congestion control logic to behave more responsibly.