Congestion control is a set of techniques that prevent computer networks from becoming so overloaded with traffic that they slow to a crawl or stop delivering data altogether. It works by regulating how fast senders push data into the network, adjusting their speed based on signs of crowding like packet loss or rising delays. Without it, the internet as we know it would routinely collapse under its own traffic.
Why Networks Get Congested
Network congestion happens when a sender transmits data faster than a bottleneck link somewhere in the path can handle. A bottleneck link is simply the slowest point between you and your destination, like a four-lane highway narrowing to one lane. When data arrives faster than that link can forward it, packets pile up in router queues. Eventually those queues overflow, and routers start dropping packets.
Here’s where things get worse. When packets are dropped, the sender assumes they were lost and retransmits them. Those retransmissions add even more traffic to an already overloaded link, causing more drops, which trigger more retransmissions. This feedback loop is called congestion collapse: the network is carrying enormous amounts of traffic, but almost none of it is useful because most of it consists of redundant retransmissions. The core job of congestion control is to keep the network operating before it reaches that tipping point.
Congestion Control vs. Flow Control
These two concepts sound similar but solve different problems. Flow control matches a sender’s speed to what the receiver can handle. If your device has a small buffer and can’t process incoming data quickly, flow control tells the sender to slow down so that buffer doesn’t overflow. It’s a conversation between two endpoints.
Congestion control, by contrast, manages traffic flowing into the network itself. It’s not about whether the receiver can keep up, but whether the routers and links between sender and receiver can keep up. Flow control operates at the data link layer and protects the receiving device. Congestion control operates at the transport and network layers and protects the shared infrastructure that everyone on the network depends on.
How TCP Manages Congestion
TCP, the protocol that handles most internet traffic, uses a “congestion window” to control how much data a sender can have in transit at any given moment. The size of this window changes constantly based on network conditions. Two key phases govern how it grows and shrinks.
Slow Start
When a connection first opens, TCP has no idea how much bandwidth is available. So it starts cautiously: it sends one packet and waits for an acknowledgment. If that acknowledgment arrives, it doubles the window to two packets. After two acknowledgments come back, it doubles again to four, then eight, and so on. Despite the name, this exponential growth actually ramps up quickly. The “slow” part refers to the fact that it doesn’t immediately blast data at full speed, which older protocols used to do. Slow start also kicks in after a period of idle time or after a collision, not just at the beginning of a connection.
Congestion Avoidance
Once the congestion window reaches a threshold (typically set by a previous congestion event), TCP switches from exponential growth to linear growth, adding capacity more cautiously. Instead of doubling the window each round, it increases by roughly one packet per round trip. This phase is about probing for available bandwidth without overshooting. When packet loss is detected, TCP treats it as a sign of congestion and cuts the window size, then begins probing upward again.
Major Congestion Control Algorithms
Over the decades, researchers have developed increasingly sophisticated approaches to deciding when and how aggressively to adjust the congestion window. Each algorithm represents a different philosophy about how to interpret network signals.
TCP Tahoe was one of the earliest implementations. It reacts to any packet loss by slamming the congestion window all the way back down to one packet and restarting slow start from scratch. Think of it as hitting the brakes hard every time you see a hint of traffic ahead. It’s safe but conservative, and it can dramatically underutilize available bandwidth after even minor packet loss.
TCP Reno improved on Tahoe by introducing “fast recovery.” When Reno detects packet loss but is still receiving some acknowledgments (meaning the network hasn’t completely stalled), it cuts the window in half instead of resetting to one. This lets it maintain a more stable data flow and recover from brief congestion episodes without the dramatic slowdown that Tahoe imposes.
CUBIC is the default congestion control algorithm in Linux and one of the most widely used on the internet today. It uses a mathematical cubic function to determine window size based on how much time has passed since the last congestion event. This makes it particularly effective on high-bandwidth, high-latency connections like long-distance links, where older algorithms would take too long to ramp back up to full speed after a loss event.
BBR (Bottleneck Bandwidth and Round-trip time), developed by Google, takes a fundamentally different approach. Rather than reacting to packet loss as the primary signal of congestion, BBR continuously estimates the available bandwidth and round-trip delay on the path, then adjusts its sending rate to match what the network can actually deliver. This avoids a classic problem with loss-based algorithms: they often fill up router buffers completely before detecting congestion, which inflates latency for everyone. BBR tries to keep throughput high while keeping delays low.
TCP Vegas also avoids waiting for packet loss. It monitors round-trip time and starts reducing its sending rate when latency increases, treating rising delay as an early warning of congestion. This proactive approach can achieve better throughput than loss-based algorithms in many conditions, since it responds before packets actually start getting dropped.
Signaling Congestion Without Dropping Packets
Traditionally, the only way routers could signal congestion was by dropping packets. The sender would notice the loss and slow down. This works, but it wastes all the network resources that were used to carry that packet up to the point where it was discarded.
Explicit Congestion Notification (ECN) offers a smarter alternative. It’s an optional feature in TCP/IP networks that lets routers mark packets with a congestion flag instead of dropping them. When a router’s queue starts filling up, it sets a specific two-bit code in the packet’s header. The receiving device sees this mark and sends the notification back to the sender, which then reduces its transmission rate. The result is the same, a slower sending rate, but no data is lost and no retransmission is needed. This saves bandwidth and reduces delays, especially on links where every dropped packet is costly.
How QUIC Changes the Game
TCP’s congestion control algorithms are built into the operating system’s kernel. Upgrading them means updating the kernel itself, which is slow and complicated at scale. QUIC, a newer transport protocol developed by Google and now used by a large portion of web traffic, takes a different approach by decoupling congestion control from the kernel entirely.
In QUIC, the congestion control algorithm runs in user-space software rather than deep in the operating system. This means applications can swap in different algorithms without touching the kernel, and updates can be deployed as easily as updating an app. QUIC also supports configuring different congestion control algorithms for different applications, so a video streaming service and a file transfer tool on the same machine can each use the strategy best suited to their needs. This flexibility has opened the door to experimenting with newer approaches, including machine-learning-based congestion control, that would be impractical to deploy through kernel updates.
What Good Congestion Control Achieves
The effectiveness of a congestion control algorithm is measured by a few key outcomes. Throughput is the most obvious: how much useful data gets delivered per second. But high throughput alone isn’t enough. Latency matters too, particularly for interactive applications like video calls and online gaming, where even small delays are noticeable. The best modern algorithms aim to maximize throughput while keeping latency low, a combination that older loss-based algorithms struggle with because they tend to fill buffers before backing off, a phenomenon known as bufferbloat.
Fairness is another critical metric. When multiple data flows share the same bottleneck link, a well-designed congestion control algorithm should give each flow a reasonable share of the bandwidth rather than letting one aggressive sender starve the others. This is especially important on the open internet, where millions of independent connections compete for the same infrastructure. The balance between being aggressive enough to use available bandwidth and being cooperative enough to share it fairly is one of the central tensions in congestion control design, and it’s the reason new algorithms go through extensive testing before widespread deployment.

