{"id":1245,"date":"2026-09-28T22:35:04","date_gmt":"2026-09-28T22:35:04","guid":{"rendered":"https:\/\/virtualserversvps.com\/blog\/?p=1245"},"modified":"2026-09-28T22:35:04","modified_gmt":"2026-09-28T22:35:04","slug":"tcp-bbr-vs-cubic-vps-delivery-rate-tcp-info","status":"publish","type":"post","link":"https:\/\/virtualserversvps.com\/blog\/tcp-bbr-vs-cubic-vps-delivery-rate-tcp-info\/","title":{"rendered":"TCP BBR vs CUBIC on a VPS WAN Link: What grep bw = (delivery_rate) Actually Tells You"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Comparing congestion control algorithms by download speed alone is how you end up with a tuning change that helps one flow shape and hurts another. The kernel exposes a far better measurement: <code>tcp_info<\/code> fields readable through <code>ss -i<\/code>, including the delivery rate the sender itself estimates. Compare BBR and CUBIC using those fields and the reason for the difference becomes visible rather than anecdotal.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Enable BBR correctly and verify it<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">BBR needs both the congestion control module and fair queueing on the egress path. Setting the sysctl without an fq qdisc leaves <code>tcp_congestion_control<\/code> reported as bbr while pacing falls back to the default behaviour, which is the most common cause of &#8220;BBR did nothing&#8221; reports.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>modprobe tcp_bbr\nsysctl net.ipv4.tcp_congestion_control=bbr\nsysctl net.core.default_qdisc=fq\nsysctl -w net.ipv4.tcp_available_congestion_control\n# net.ipv4.tcp_available_congestion_control = reno cubic bbr\nsysctl -w net.ipv4.tcp_congestion_control\nip route show default\n# confirm the qdisc actually attached\nip -s link show dev eth0 | head -5\ntc qdisc show dev eth0<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Persist with <code>\/etc\/sysctl.d\/99-bbr.conf<\/code> and load the module at boot via <code>\/etc\/modules-load.d\/bbr.conf<\/code>. Verify after a reboot rather than assuming.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Read the right tcp_info fields<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Run a transfer and inspect the socket while it is live. <code>ss -tin<\/code> prints a set of fields that are the actual evidence:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ss -tin state established '( dport = :443 or sport = :443 )' | head -20\n\n# fields to compare:\n#   rtt:X\/Y   smoothed rtt \/ rtt variance, microseconds\n#   cwnd:N    congestion window in segments\n#   send Zbps  application-limited send rate\n#   bw = X    BBR's delivery-rate estimate (only present under bbr)\n#   retrans:X\/Y  retransmitted \/ total segments\n#   fack, lost, dsack  loss accounting\n#   pacing_rate  the pacer's current target (bbr only)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Under CUBIC, <code>bw<\/code> and <code>pacing_rate<\/code> are absent, so you infer throughput from <code>cwnd<\/code> divided by <code>rtt<\/code>. Under BBR, <code>bw<\/code> is the sender&#8217;s own estimate of the bottleneck delivery rate &#8211; a much more direct number, and one that stays informative when the connection is application-limited and the cwnd-derived estimate collapses to nonsense.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Condition<\/th><th>CUBIC behaviour<\/th><th>BBR behaviour<\/th><th>Diagnostic<\/th><\/tr><\/thead><tbody><tr><td>1% random loss<\/td><td>halves cwnd, throughput drop<\/td><td>largely ignores non-congestive loss<\/td><td>retrans count vs cwnd curve<\/td><\/tr><tr><td>128 KB buffer at bottleneck<\/td><td>loss-driven sawtooth<\/td><td>probes for the buffer floor<\/td><td>compare bw to paced rate<\/td><\/tr><tr><td>High RTT (150 ms+)<\/td><td>slow convergence<\/td><td>converges in ~1 RTT<\/td><td>rtt field plus bw ramp<\/td><\/tr><tr><td>Shallow buffer, no loss<\/td><td>cwnd grows until loss<\/td><td>stabilizes below queue limit<\/td><td>tc -s qdisc backlog<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Measure both without network noise<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Interleave the two algorithms against the same endpoint within the same minute to cancel out external load:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>for cc in cubic bbr; do\n  sysctl -qw net.ipv4.tcp_congestion_control=$cc\n  echo \"== $cc ==\"\n  curl -o \/dev\/null -s -w 'connect=%{time_connect} ttfb=%{time_starttransfer} total=%{time_total} bytes=%{size_download}\\n' \\\n    --limit-rate 0 https:\/\/mirror.example.net\/100mb.bin\n  sleep 5\ndone\n\n# per-connection retransmit view during the run\nnstat -az TcpRetransSegs TcpExtTCPLostRetransmit TcpExtTCPFastRetrans\n# queue backlog at the egress\ntc -s qdisc show dev eth0<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">On a VPS, the uplink is usually shared and the bottleneck is frequently the hypervisor&#8217;s vNIC or the upstream switch port, not the path. If <code>bw<\/code> plateaus at a value far below your provisioned port rate and <code>tc -s qdisc<\/code> shows a persistent backlog with zero drops, you are queue-limited by the host, and no congestion control change will help. Detecting that early saves a lot of tuning.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Where BBR is the wrong answer<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">BBR v1 is aggressive about probing for bandwidth and can unfairly starve CUBIC flows sharing a bottleneck, which matters on a VPS whose uplink is policed by the provider. It also does not respond to loss the way operators expect, so a genuinely congested path can show high <code>bw<\/code> estimates while real goodput &#8211; the bytes the peer confirms &#8211; stays flat. Cross-check with application-level counters, not just <code>ss<\/code>.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Keep BBR for long-haul, high-RTT, moderately lossy paths (intercontinental replication, file sync to remote regions).<\/li><li>Keep CUBIC for low-RTT paths where you share the link with other tenants and fairness matters.<\/li><li>Use <code>net.core.default_qdisc=fq<\/code> with BBR and <code>fq_codel<\/code> with CUBIC; a mismatched qdisc hides the effect you are measuring.<\/li><li>Check <code>nstat<\/code> retransmit counters between runs, not only wall-clock transfer time.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">If the delivery-rate estimate saturates at a rate well under your port speed during every test, the constraint is the host&#8217;s egress policing rather than the kernel. That is a provisioning question: our <a href=\"https:\/\/virtualserversvps.com\/\">VPS network specifications and port-rate details<\/a> list the sustained egress each tier is policed to, which is the number to compare your measured <code>bw<\/code> against.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Watch the pacer, not the peak<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">BBR&#8217;s advantage is stability under shallow buffers, and <code>pacing_rate<\/code> is where it shows. Sample it repeatedly during a transfer and look at the variance rather than the maximum. A pacer that holds a tight band around a stable rate is doing its job; one that swings by a factor of three between samples indicates the delivery-rate estimate is being perturbed by loss or by another flow on the same bottleneck.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># sample pacing_rate and delivery rate 10x during a transfer\nfor i in $(seq 10); do\n  ss -tin state established '( dport = :443 )' | grep -o 'bw=[^ ]*\\|pacing_rate [^ ]*'\n  sleep 1\ndone | sort | uniq -c | sort -rn\n\n# correlate with host-level egress contention\ncat \/proc\/net\/dev | awk '\/eth0\/{print \"tx_drop=\" $4, \"tx_fifo=\" $3}'\nmpstat -P ALL 1 3<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If the variance is large and <code>tx_fifo<\/code> grows while <code>tx_drop<\/code> stays flat, the queue on the host side is absorbing the bursts and adding latency without losing packets &#8211; a bufferbloat symptom, best addressed with <code>fq_codel<\/code> and a sane <code>txqueuelen<\/code> rather than with a congestion control swap.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Sizing the test to the instance<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Congestion control comparison on a 1-vCPU instance has a hard ceiling: a single core may not generate enough packets to saturate a multi-gigabit uplink, in which case the sender is the bottleneck and both algorithms measure the same wall. Check <code>mpstat<\/code> for the <code>softirq<\/code> column during the transfer. If softirq approaches one full core, move to a larger instance or pin the receiver across queues before drawing conclusions about the algorithm. The vCPU and port-rate figures per tier are listed on our <a href=\"https:\/\/virtualserversvps.com\/\">VPS plans and network specifications page<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Comparing congestion control algorithms by download speed alone is how you end up with a tuning change that helps one flow shape and hurts another. The kernel exposes a far&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":1,"footnotes":""},"categories":[3],"tags":[],"class_list":["post-1245","post","type-post","status-publish","format-standard","hentry","category-performance-optimization"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.1 (Yoast SEO v26.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>TCP BBR vs CUBIC on a VPS WAN Link: What grep bw = (delivery_rate) Actually Tells You - Virtual Servers VPS Blog<\/title>\n<meta name=\"description\" content=\"Comparing congestion control algorithms by download speed alone is how you end up with a tuning change that helps one flow shape and hurts another. The\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/virtualserversvps.com\/blog\/tcp-bbr-vs-cubic-vps-delivery-rate-tcp-info\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"TCP BBR vs CUBIC on a VPS WAN Link: What grep bw = (delivery_rate) Actually Tells You\" \/>\n<meta property=\"og:description\" content=\"TCP BBR vs CUBIC on a VPS WAN Link: What grep bw = (delivery_rate) Actually Tells You\" \/>\n<meta property=\"og:url\" content=\"https:\/\/virtualserversvps.com\/blog\/tcp-bbr-vs-cubic-vps-delivery-rate-tcp-info\/\" \/>\n<meta property=\"og:site_name\" content=\"Virtual Servers VPS Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-28T22:35:04+00:00\" \/>\n<meta name=\"author\" content=\"Virtual-Servers-Vps-Editor\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Virtual-Servers-Vps-Editor\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/tcp-bbr-vs-cubic-vps-delivery-rate-tcp-info\/\",\"url\":\"https:\/\/virtualserversvps.com\/blog\/tcp-bbr-vs-cubic-vps-delivery-rate-tcp-info\/\",\"name\":\"TCP BBR vs CUBIC on a VPS WAN Link: What grep bw = (delivery_rate) Actually Tells You - Virtual Servers VPS Blog\",\"isPartOf\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#website\"},\"datePublished\":\"2026-09-28T22:35:04+00:00\",\"author\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0\"},\"description\":\"Comparing congestion control algorithms by download speed alone is how you end up with a tuning change that helps one flow shape and hurts another. The\",\"breadcrumb\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/tcp-bbr-vs-cubic-vps-delivery-rate-tcp-info\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/virtualserversvps.com\/blog\/tcp-bbr-vs-cubic-vps-delivery-rate-tcp-info\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/tcp-bbr-vs-cubic-vps-delivery-rate-tcp-info\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/virtualserversvps.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"TCP BBR vs CUBIC on a VPS WAN Link: What grep bw = (delivery_rate) Actually Tells You\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#website\",\"url\":\"https:\/\/virtualserversvps.com\/blog\/\",\"name\":\"Virtual Servers VPS Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/virtualserversvps.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0\",\"name\":\"Virtual-Servers-Vps-Editor\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g\",\"caption\":\"Virtual-Servers-Vps-Editor\"},\"sameAs\":[\"https:\/\/virtualserversvps.com\/blog\"],\"url\":\"https:\/\/virtualserversvps.com\/blog\/author\/virtualserversvps\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"TCP BBR vs CUBIC on a VPS WAN Link: What grep bw = (delivery_rate) Actually Tells You - Virtual Servers VPS Blog","description":"Comparing congestion control algorithms by download speed alone is how you end up with a tuning change that helps one flow shape and hurts another. The","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/virtualserversvps.com\/blog\/tcp-bbr-vs-cubic-vps-delivery-rate-tcp-info\/","og_locale":"en_US","og_type":"article","og_title":"TCP BBR vs CUBIC on a VPS WAN Link: What grep bw = (delivery_rate) Actually Tells You","og_description":"TCP BBR vs CUBIC on a VPS WAN Link: What grep bw = (delivery_rate) Actually Tells You","og_url":"https:\/\/virtualserversvps.com\/blog\/tcp-bbr-vs-cubic-vps-delivery-rate-tcp-info\/","og_site_name":"Virtual Servers VPS Blog","article_published_time":"2026-09-28T22:35:04+00:00","author":"Virtual-Servers-Vps-Editor","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Virtual-Servers-Vps-Editor","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/virtualserversvps.com\/blog\/tcp-bbr-vs-cubic-vps-delivery-rate-tcp-info\/","url":"https:\/\/virtualserversvps.com\/blog\/tcp-bbr-vs-cubic-vps-delivery-rate-tcp-info\/","name":"TCP BBR vs CUBIC on a VPS WAN Link: What grep bw = (delivery_rate) Actually Tells You - Virtual Servers VPS Blog","isPartOf":{"@id":"https:\/\/virtualserversvps.com\/blog\/#website"},"datePublished":"2026-09-28T22:35:04+00:00","author":{"@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0"},"description":"Comparing congestion control algorithms by download speed alone is how you end up with a tuning change that helps one flow shape and hurts another. The","breadcrumb":{"@id":"https:\/\/virtualserversvps.com\/blog\/tcp-bbr-vs-cubic-vps-delivery-rate-tcp-info\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/virtualserversvps.com\/blog\/tcp-bbr-vs-cubic-vps-delivery-rate-tcp-info\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/virtualserversvps.com\/blog\/tcp-bbr-vs-cubic-vps-delivery-rate-tcp-info\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/virtualserversvps.com\/blog\/"},{"@type":"ListItem","position":2,"name":"TCP BBR vs CUBIC on a VPS WAN Link: What grep bw = (delivery_rate) Actually Tells You"}]},{"@type":"WebSite","@id":"https:\/\/virtualserversvps.com\/blog\/#website","url":"https:\/\/virtualserversvps.com\/blog\/","name":"Virtual Servers VPS Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/virtualserversvps.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0","name":"Virtual-Servers-Vps-Editor","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g","caption":"Virtual-Servers-Vps-Editor"},"sameAs":["https:\/\/virtualserversvps.com\/blog"],"url":"https:\/\/virtualserversvps.com\/blog\/author\/virtualserversvps\/"}]}},"_links":{"self":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/1245","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/comments?post=1245"}],"version-history":[{"count":1,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/1245\/revisions"}],"predecessor-version":[{"id":1248,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/1245\/revisions\/1248"}],"wp:attachment":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/media?parent=1245"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/categories?post=1245"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/tags?post=1245"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}