Optimize your Linux kernel with BBR congestion control to fix network bottlenecks in Docker. Learn how to boost throughput and stabilize high-latency flows.
During a recent migration of a data-heavy microservice, we hit a wall where our Docker containers were struggling to saturate a 10Gbps link despite having plenty of CPU headroom. The issue wasn't the application code or the container orchestration; it was the default TCP congestion control algorithm choking on the long-haul network latency between our regions.
Switching to BBR (Bottleneck Bandwidth and Round-trip propagation time) is one of the lowest-effort, highest-impact changes you can make to your networking stack. If you're running high-throughput workloads, the default CUBIC algorithm often leaves significant performance on the table.
Most standard Linux distributions ship with CUBIC as the default congestion control algorithm. CUBIC is loss-based; it assumes that packet loss is a signal of network congestion. In modern high-speed, high-latency environments, this assumption is often wrong. You might experience minor packet loss due to transient interference, causing CUBIC to aggressively throttle your throughput unnecessarily.
BBR, developed by Google and integrated into the Linux kernel since version 4.9, is model-based. It estimates the actual bottleneck bandwidth and the round-trip time (RTT) of the path. Instead of reacting blindly to packet loss, it sends data at the rate the network can actually handle. For Docker containers, which often share a host's network namespace and kernel resources, this means more consistent performance and fewer "stuttering" connections.
If you’ve already been down the rabbit hole of Linux Sysctl Tuning for High-Performance Docker Networking, enabling BBR is the logical next step to squeeze every bit of efficiency out of your traffic.
Before you start, check if your kernel actually supports BBR. Run the following on your host:
Bashsysctl net.ipv4.tcp_congestion_control
If it returns cubic or reno, you're using the old defaults. To see if BBR is available as a module, check your current configuration:
Bashsysctl net.ipv4.tcp_available_congestion_control
If you don't see bbr in the output, your kernel is likely older than 4.9. In that case, it's time for an upgrade. I usually prefer running newer kernels on my Docker hosts to stay ahead of these types of bottlenecks, especially when dealing with Linux Kernel Tuning: Fixing Socket Exhaustion in Docker Proxies where newer netfilter features can save your bacon.
You don't need to configure anything inside your containers. Because the TCP stack is managed by the host kernel, enabling BBR globally affects every container running on that host.
Create or edit /etc/sysctl.d/99-bbr.conf and add the following lines:
INInet.core.default_qdisc = fq net.ipv4.tcp_congestion_control = bbr
The fq (Fair Queuing) packet scheduler is a requirement for BBR to function correctly, as it helps pace the packets. Apply these changes immediately by running:
Bashsudo sysctl --system
You can verify it took effect by checking the current congestion control again:
Bashcat /proc/sys/net/ipv4/tcp_congestion_control # Should output: bbr
I’ve seen engineers rush to enable BBR on every box in their fleet, but there’s a nuance here. BBR is fantastic for throughput, but it can be more aggressive than CUBIC. If you have a network path that is heavily congested with CUBIC-based flows, BBR might "steal" bandwidth, potentially causing fairness issues.
We once tried enabling it on a legacy transit server that handled a massive mix of mixed-protocol traffic, and we noticed a slight increase in jitter for some UDP-based services. We rolled it back on that specific node. Always test in staging before pushing to production, especially if your network topology is complex.
Also, don't confuse this with Bandwidth Throttling with eBPF and Linux Traffic Control. BBR manages how you use the available bandwidth to avoid congestion; it doesn't artificially cap your speed. If you need to strictly limit a noisy neighbor container, stick to tc (Traffic Control) rules.
Does BBR break container isolation? No. BBR operates at the host kernel level, managing the TCP stack for all sockets. It doesn't bypass any namespace or cgroup limits you've placed on your containers.
Do I need to restart my Docker containers? Generally, no. The kernel applies the change to the TCP stack immediately. However, existing long-lived connections might not switch algorithms until they are re-established. A rolling restart of your services is usually a good practice to ensure all active sockets are utilizing the new congestion control.
Is BBR safe for internal LAN traffic? It's safe, but you might see diminishing returns. BBR shines on high-latency links (like cross-region traffic or connections over the public internet). On a low-latency 10Gbps LAN, the differences between CUBIC and BBR are often negligible.
Implementing BBR is a high-leverage move for any engineer managing high-throughput Docker hosts. It’s one of those rare "set it and forget it" optimizations that makes a measurable difference in network stability. Just remember to monitor your egress metrics after the change—if you see strange spikes in tail latency, don't be afraid to dial it back or investigate your queue disciplines further. Networking in Linux is rarely a silver bullet, but BBR gets us closer than anything else I've tested.
Linux kernel tuning is essential when your Docker proxies hit socket exhaustion. Learn how to optimize your TCP stack to handle high-concurrency traffic.
Read moreLearn how to use eBPF and Linux Traffic Control for precise bandwidth throttling in Docker. Prevent noisy containers from starving your apps of network resources.