Skip to main content

Google BBR

BBR (Bottleneck Bandwidth and Round-trip propagation time) is a Linux TCP congestion control algorithm that targets high throughput with lower latency by pacing traffic based on an estimated model of bandwidth and RTT, rather than pushing until packet loss occurs.

Background and history

Traditional congestion controls (such as Reno and CUBIC) are primarily loss-based: they increase sending rates until loss signals congestion. This can inflate queues and cause latency spikes (bufferbloat). BBR was introduced by Google in 2016 as a model-based approach that estimates the bottleneck bandwidth and the minimum RTT, then paces traffic to avoid persistent queue buildup.

Adoption and where it’s commonly used

BBR is commonly enabled on:

  • VPS and cloud servers serving global users over variable networks
  • High-throughput HTTP(S) endpoints and APIs
  • Long-fat networks where latency and bandwidth-delay product matter
  • Content delivery and streaming stacks that benefit from stable pacing

Best when to use

  • You serve users over diverse networks and want steadier throughput with reduced queue latency.
  • Your workload is dominated by TCP traffic (HTTPS, HTTP/2, SSH/SFTP, database replication).
  • You want a low-touch kernel-level change that does not require application changes.
  • You operate OpenLiteSpeed with HTTP/3 and need to increase UDP socket buffers to avoid QUIC send buffer issues.

Not suitable when

  • You require strict fairness with other flows in shared environments where policies mandate specific congestion control behavior.
  • You are in a tightly controlled enterprise network where congestion control settings are standardized and audited.
  • You cannot test safely and revert quickly (kernel-level tuning impacts all TCP traffic on the host).
  • You expect BBR to replace capacity planning, caching, or application optimization (it does not).

Compatibility notes

  • TCP BBR requires a Linux kernel that includes the tcp_bbr module (commonly available in kernel 4.9+).
  • Some distributions ship BBR as a module; others compile it into the kernel.
  • BBR tuning is TCP-focused. HTTP/3 runs over QUIC on UDP, so OS-level UDP buffer sizing matters for stability, but QUIC congestion control is implemented in user space by the HTTP/3 stack.
  • Firewall rules must allow UDP/443 for HTTP/3.
  • On SELinux-enforcing distributions, firewall and service contexts may require additional validation (depends on your stack and policy).
Production impact

Changing congestion control affects all TCP connections on the host. Apply during a maintenance window when possible and verify with controlled tests before relying on it.

Concepts and how it works

Loss-based vs model-based congestion control

ApproachTypical algorithmsWhat increases sending rateCommon side effect
------
Loss-basedReno, CUBICIncrease until loss signals congestionQueue growth and latency under load
Model-basedBBREstimate bandwidth and RTT, pace accordinglyDifferent fairness behavior vs loss-based flows

Components involved

  • Congestion control: controls TCP send rate (net.ipv4.tcp_congestion_control)
  • Queueing discipline (qdisc): packet scheduling in the kernel (net.core.default_qdisc)
  • Socket buffers: kernel memory for network I/O (net.core.rmem_max, net.core.wmem_max) Useful for UDP-heavy HTTP/3 workloads that can hit default buffer limits.

Prerequisites

  • Root or sudo access

  • Kernel supports BBR (tcp_bbr)

  • Ability to revert changes (console/serial access recommended for remote servers)

  • For HTTP/3:

    • OpenLiteSpeed installed and configured
    • UDP/443 allowed at host and provider firewall

Installation and enablement

Step 1: Confirm kernel support (read-only)

Check kernel version:

uname -r

Check available congestion control algorithms:

sysctl net.ipv4.tcp_available_congestion_control

If you see bbr listed, the kernel supports it.

Step 2: Load the BBR module (if needed)

Attempt to load:

sudo modprobe tcp_bbr

Confirm loaded:

lsmod | grep -E '^tcp_bbr\b' || true

Make module load persistent (module-based systems):

echo "tcp_bbr" | sudo tee /etc/modules-load.d/bbr.conf >/dev/null
Correction

Many guides edit /etc/sysctl.conf directly. A safer, more maintainable approach is to use a dedicated file in /etc/sysctl.d/ so changes are explicit and easier to manage and revert.

Step 3: Apply sysctl tuning via /etc/sysctl.d/

Create a dedicated sysctl file:

sudo tee /etc/sysctl.d/99-bbr.conf >/dev/null <<'EOF'
# Enable fair-queueing for better pacing behavior
net.core.default_qdisc = fq

# Enable BBR congestion control for TCP
net.ipv4.tcp_congestion_control = bbr

# UDP socket buffers (useful for high-throughput QUIC/HTTP/3)
net.core.rmem_max = 26214400
net.core.wmem_max = 26214400
EOF

Apply:

sudo sysctl --system
Buffer sizing

The rmem_max/wmem_max values are examples. On very small VPS instances, setting excessively high socket buffers can increase memory pressure. If you run with 1 GB RAM or less, consider starting lower (for example 8–16 MB) and increase only if logs indicate buffer exhaustion.

OpenLiteSpeed HTTP/3 and QUIC alignment

BBR (TCP) improves TCP pacing. For HTTP/3 (QUIC over UDP), stability usually depends on:

  • UDP/443 reachability
  • Adequate UDP socket buffers
  • Correct OpenLiteSpeed QUIC configuration (HTTP/3 enabled)

Confirm UDP/443 is reachable

Host firewall (UFW):

sudo ufw allow 443/udp
sudo ufw status verbose

firewalld:

sudo firewall-cmd --permanent --add-port=443/udp
sudo firewall-cmd --reload
sudo firewall-cmd --list-ports
Firewall safety

Only open UDP/443 if your server is intended to serve QUIC/HTTP/3 on 443. Avoid opening additional UDP ports unless required by your stack.

Configure OpenLiteSpeed QUIC settings (CLI-only)

OpenLiteSpeed configuration layouts vary by version and deployment. Treat direct XML edits as an advanced operation.

Safe prep (read-only)

Locate config:

sudo ls -la /usr/local/lsws/conf/ 2>/dev/null || true
sudo test -f /usr/local/lsws/conf/httpd_config.xml && echo "Found httpd_config.xml" || true

Backup before changes:

sudo cp /usr/local/lsws/conf/httpd_config.xml /usr/local/lsws/conf/httpd_config.xml.bak.$(date +%F_%H%M%S)

Patch approach

Use one approach consistently. xmlstarlet is safer than sed for XML, but may not be installed.

sudo bash -c '
OLS_CONF="/usr/local/lsws/conf/httpd_config.xml"

# Ensure file exists
test -f "$OLS_CONF" || { echo "Missing: $OLS_CONF"; exit 1; }

# Force/insert quicEnable = 1
if grep -q "<quicEnable>" "$OLS_CONF"; then
sed -i "s|<quicEnable>.*</quicEnable>|<quicEnable>1</quicEnable>|" "$OLS_CONF"
else
sed -i "s|</tuning>| <quicEnable>1</quicEnable>\n</tuning>|" "$OLS_CONF"
fi

# Force/insert quicCongestionControl = BBR
if grep -q "<quicCongestionControl>" "$OLS_CONF"; then
sed -i "s|<quicCongestionControl>.*</quicCongestionControl>|<quicCongestionControl>BBR</quicCongestionControl>|" "$OLS_CONF"
else
sed -i "s|</tuning>| <quicCongestionControl>BBR</quicCongestionControl>\n</tuning>|" "$OLS_CONF"
fi
'

Restart OpenLiteSpeed:

sudo systemctl restart lsws 2>/dev/null || sudo /usr/local/lsws/bin/lswsctrl restart
OpenLiteSpeed configuration variability

If quicEnable or quicCongestionControl do not exist in your XML, inserting them in the wrong section can break configuration parsing. Validate by checking OpenLiteSpeed startup logs after restart and be prepared to revert to the backup file.

Verification

Verify BBR is enabled for TCP

sysctl net.ipv4.tcp_congestion_control

Expected:

net.ipv4.tcp_congestion_control = bbr

Confirm BBR is available:

sysctl net.ipv4.tcp_available_congestion_control

Confirm qdisc:

sysctl net.core.default_qdisc

Confirm UDP buffer values

sysctl net.core.rmem_max
sysctl net.core.wmem_max

Confirm active TCP sessions show BBR (when traffic exists)

This works best when you have established TCP connections:

ss -tni | grep -i bbr || true

Verify HTTP/3 advertisement (alt-svc)

Check response headers:

curl -I https://yourdomain.com 2>&1 | grep -i "alt-svc" || true

A typical header indicates HTTP/3 availability on 443.

If your local curl supports HTTP/3, you can attempt a direct HTTP/3 request:

curl --http3 -I https://yourdomain.com

Check OpenLiteSpeed logs for UDP buffer errors

sudo grep -i "sendmmsg" /usr/local/lsws/logs/error.log || true

If you see repeated sendmmsg failures under load, increase UDP buffers gradually and re-test.

Practical use cases

Use case: Reduce latency spikes under load (TCP-heavy sites)

  • Enable BBR + fq
  • Validate congestion control and qdisc
  • Run a controlled load test and compare TTFB and tail latency before/after

Use case: Stabilize HTTP/3 on OpenLiteSpeed

  • Ensure UDP/443 is allowed at provider and host firewall
  • Increase UDP buffers (rmem_max/wmem_max)
  • Confirm alt-svc header and monitor OLS logs for send buffer errors

Troubleshooting

bbr not available in tcp_available_congestion_control

Likely causes:

  • Kernel too old
  • Kernel built without tcp_bbr
  • Module not loaded

Actions:

uname -r
sudo modprobe tcp_bbr
sysctl net.ipv4.tcp_available_congestion_control

If it still does not appear, upgrade to a kernel that includes BBR.

sysctl applies but traffic does not improve

Common reasons:

  • Bottleneck is not congestion control (CPU, TLS, PHP, database, disk I/O)
  • Latency is dominated by application time
  • Network path characteristics do not benefit from BBR

Actions:

  • Confirm real bottleneck using system monitoring (htop, btop, iotop, iftop)
  • Compare latency under load before/after with consistent tests

HTTP/3 not working after enabling UDP/443

Common causes:

  • Provider firewall blocks UDP/443
  • OpenLiteSpeed not actually serving QUIC
  • TLS/ALPN configuration does not advertise HTTP/3

Actions:

sudo ufw status verbose 2>/dev/null || true
sudo ss -uapn | grep ":443" || true
curl -I https://yourdomain.com 2>&1 | grep -i "alt-svc" || true
sudo tail -n 200 /usr/local/lsws/logs/error.log 2>/dev/null || true

OpenLiteSpeed fails to restart after XML edits

Actions:

  • Revert to the backup file
  • Restart again
  • Inspect logs
sudo cp /usr/local/lsws/conf/httpd_config.xml.bak.* /usr/local/lsws/conf/httpd_config.xml
sudo systemctl restart lsws 2>/dev/null || sudo /usr/local/lsws/bin/lswsctrl restart
sudo tail -n 200 /usr/local/lsws/logs/error.log 2>/dev/null || true

Security notes

  • Enabling UDP/443 exposes an additional transport path to your server. Keep web server and TLS configuration updated and monitor traffic.
  • Kernel tuning changes affect the entire host. Document what you changed and keep a rollback plan.
  • Avoid applying performance tuning during an ongoing incident unless you can verify changes and revert quickly.

Quick reference

SettingPurposeTypical value
--
net.core.default_qdiscQueueing discipline for pacingfq
net.ipv4.tcp_congestion_controlTCP congestion controlbbr
net.core.rmem_maxMax UDP receive buffer26214400 (example)
net.core.wmem_maxMax UDP send buffer26214400 (example)

Apply and verify

sudo modprobe tcp_bbr
sudo sysctl --system

sysctl net.ipv4.tcp_congestion_control
sysctl net.core.default_qdisc
sysctl net.core.rmem_max
sysctl net.core.wmem_max