{"id":518,"date":"2026-06-26T02:39:15","date_gmt":"2026-06-26T02:39:15","guid":{"rendered":"https:\/\/virtualserversvps.com\/blog\/?p=518"},"modified":"2026-09-25T22:04:12","modified_gmt":"2026-09-25T22:04:12","slug":"vps-network-performance-how-to-measure-and-improve-throughput-and-latency","status":"publish","type":"post","link":"https:\/\/virtualserversvps.com\/blog\/vps-network-performance-how-to-measure-and-improve-throughput-and-latency\/","title":{"rendered":"Tuning TCP and NIC Offloads for VPS Throughput: SO_SNDBUF, TSO\/GSO, and RTT-Based Buffer Sizing"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Network tuning advice for VPS hosts is usually a list of sysctl values copied from a 2013 bare-metal guide. Most of it is wrong in two specific ways: it ignores BDP math, and it ignores virtualized NIC offload behaviour. This article derives the buffer sizes your link actually needs, then shows how to verify that the guest and the host agree about segmentation offloads &mdash; the single most common cause of a network path that benchmarks at 10 Gbps but delivers 200 Mbps in production.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Start From the Bandwidth-Delay Product, Not From a Blog Post<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Socket buffers exist to keep the pipe full while waiting for an ACK. The amount of data in flight at any moment is <code>BDP = bandwidth &times; RTT<\/code>. For a 1 Gbps link with 40 ms RTT:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># 1 Gbit\/s = 125 MB\/s; RTT 40 ms\n# BDP = 125 * 0.040 = 5 MB\n# one socket needs ~5 MB in flight -> rmem\/wmem of ~6 MB to be safe<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now compute it for the VPS you actually rent and set the values accordingly:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/bin\/bash\n# bdp.sh - print required socket buffers for a link\nBW_MBPS=$1   # link speed in Mbit\/s\nRTT_MS=$2    # measured RTT in ms\npython3 - \"$BW_MBPS\" \"$RTT_MS\" <<'PY'\nimport sys\nbw = float(sys.argv[1]) \/ 8 * 1_000_000   # bytes\/s\nrtt = float(sys.argv[2]) \/ 1000           # seconds\nbdp = bw * rtt\nprint(f\"BDP          = {bdp\/1e6:.2f} MB\")\nprint(f\"tcp_rmem max = {int(bdp*1.5)}\")\nprint(f\"tcp_wmem max = {int(bdp*1.5)}\")\nPY\n.\/bdp.sh 1000 40<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Apply the result and let autotuning work from a correct ceiling rather than an arbitrary one:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat >> \/etc\/sysctl.d\/99-net-bdp.conf <<'EOF'\nnet.core.rmem_max = 8388608\nnet.core.wmem_max = 8388608\nnet.ipv4.tcp_rmem = 4096 131072 8388608\nnet.ipv4.tcp_wmem = 4096 65536 8388608\nnet.core.netdev_max_backlog = 5000\nnet.ipv4.tcp_mtu_probing = 2\nEOF\nsysctl --system<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">The Real Killer: Offload State Mismatch Across virtio<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">When a guest sends a 64 KB TCP segment, it depends on the virtual NIC to hand the kernel a segment large enough for the hardware (or host) to split. If the guest advertises TSO\/GSO\/GRO but the vhost-net backend has them disabled &mdash; or the traffic is bridged through a device that cannot handle large segments &mdash; the host performs software segmentation of every packet. Throughput collapses and per-packet CPU rises. Check both ends:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># inside the guest\nethtool -k eth0 | egrep 'tso|gso|gro|gso|tx-checksum'\nethtool -S eth0 | egrep 'tx_queue_stop|tx_timeout|seg'\n\n# confirm the virtual device type\nethtool -i eth0\n# virtio_net is good; e1000 \/ rtl8139 emulated NICs are the problem\n\n# verify MSS clamping if traffic is tunnelled\nip -d link show eth0\niptables -t mangle -L -n -v | grep -i mss<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you are on an emulated NIC rather than <code>virtio-net<\/code>, no amount of sysctl tuning will get you past roughly 1 Gbps of CPU-bound throughput. That is a provider decision: ask about it before you buy, and factor it into <a href=\"https:\/\/virtualserversvps.com\/\">how the plans on virtualserversvps.com handle network virtualization<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Measure the Path Before You Tune It<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Use <code>iperf3<\/code> for raw capacity, but measure it in the right direction (many VPS links are asymmetric), then use <code>ss<\/code> to see the actual congestion window and RTT the kernel is working with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># server side\niperf3 -s\n\n# client: 4 parallel streams, 60s, report per-stream\niperf3 -c target.example.net -P 4 -t 60 -O 5 --json | jq '.end.sum_sent.bits_per_second\/1e6'\n\n# watch cwnd, rtt and retransmits for a live connection\nss -tin state established '( dport = :443 )' | head -40\n# look for: rtt, rttvar, cwnd, retrans, ssthresh\n\n# count retransmissions system-wide\nnstat -az TcpRetransSegs TcpExtTCPLostRetransmit<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A healthy long-lived connection on a 1 Gbps link with 40 ms RTT should hold <code>cwnd<\/code> in the 200&ndash;400 segment range. If <code>cwnd<\/code> stays under 20 and <code>retrans<\/code> climbs, you have loss, not a buffer problem &mdash; go find it with <code>mtr<\/code> and packet captures rather than raising <code>rmem_max<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Symptom<\/th><th>Likely cause<\/th><th>Wrong fix<\/th><th>Right fix<\/th><\/tr><\/thead><tbody><tr><td>Throughput plateaus far below link speed, low CPU<\/td><td>Socket buffer ceiling too low for BDP<\/td><td>More vCPUs<\/td><td>Raise <code>tcp_rmem<\/code>\/<code>tcp_wmem<\/code> max<\/td><\/tr><tr><td>Throughput plateaus, 100% softirq on one core<\/td><td>Offload mismatch, software segmentation<\/td><td>Raise buffers<\/td><td>Enable TSO\/GSO\/GRO consistently, use virtio-net<\/td><\/tr><tr><td>Latency spikes under load, buffers full<\/td><td>Bufferbloat in the virtual switch<\/td><td>Bigger buffers<\/td><td>Fair queueing, smaller queues, BBR<\/td><\/tr><tr><td>Slow single connection, fast parallel<\/td><td>Window-limited single flow<\/td><td>More parallel flows<\/td><td>Fix BDP sizing, check <code>cwnd<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Congestion Control and Queue Discipline Together<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">BBR is a large win on lossy or bufferbloated paths but does nothing for an idle link; fq_codel fixes bufferbloat but relies on the sender behaving. Use both, and verify:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sysctl -w net.ipv4.tcp_congestion_control=bbr\nsysctl -w net.core.default_qdisc=fq_codel\nsysctl -w net.ipv4.tcp_notsent_lowat=131072\n\nsysctl net.ipv4.tcp_available_congestion_control\ntc qdisc show dev eth0\nss -tin | grep -o 'bbr' | head -3<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>tcp_notsent_lowat<\/code> deserves special mention for request\/response workloads: it stops the kernel from queuing megabytes of unacknowledged data that will never help, which measurably reduces TTFB under load without any downside on throughput. If your bottleneck turns out to be application-side rather than kernel-side, <a href=\"https:\/\/virtualserversvps.com\/\">the hosting comparisons on virtualserversvps.com<\/a> cover when moving up a plan beats tuning one.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Verification Loop<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>Compute the BDP for your real RTT before setting any buffer value.<\/li><li>Confirm <code>virtio-net<\/code> and matching offload flags on both ends of the vhost path.<\/li><li>Measure with <code>iperf3 -P 4 --json<\/code> and inspect <code>ss -tin<\/code>, not just final throughput.<\/li><li>Add <code>fq_codel<\/code> plus BBR, then re-measure p99 latency under saturation, not idle throughput.<\/li><li>Set <code>tcp_notsent_lowat<\/code> for latency-sensitive APIs.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">A tuned VPS network is one where every buffer value can be traced to an arithmetic derivation, and every offload flag has been verified on both sides of the hypervisor boundary.<\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>Network tuning advice for VPS hosts is usually a list of sysctl values copied from a 2013 bare-metal guide. Most of it is wrong in two specific ways: it ignores&#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":11,"footnotes":""},"categories":[3],"tags":[],"class_list":["post-518","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>Tuning TCP and NIC Offloads for VPS Throughput: SO_SNDBUF, TSO\/GSO, and RTT-Based Buffer Sizing - Virtual Servers VPS Blog<\/title>\n<meta name=\"description\" content=\"Network tuning advice for VPS hosts is usually a list of sysctl values copied from a 2013 bare-metal guide. Most of it is wrong in two specific ways: it\" \/>\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\/vps-network-performance-how-to-measure-and-improve-throughput-and-latency\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Tuning TCP and NIC Offloads for VPS Throughput: SO_SNDBUF, TSO\/GSO, and RTT-Based Buffer Sizing\" \/>\n<meta property=\"og:description\" content=\"Tuning TCP and NIC Offloads for VPS Throughput: SO_SNDBUF, TSO\/GSO, and RTT-Based Buffer Sizing\" \/>\n<meta property=\"og:url\" content=\"https:\/\/virtualserversvps.com\/blog\/vps-network-performance-how-to-measure-and-improve-throughput-and-latency\/\" \/>\n<meta property=\"og:site_name\" content=\"Virtual Servers VPS Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-06-26T02:39:15+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-25T22:04:12+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=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/vps-network-performance-how-to-measure-and-improve-throughput-and-latency\/\",\"url\":\"https:\/\/virtualserversvps.com\/blog\/vps-network-performance-how-to-measure-and-improve-throughput-and-latency\/\",\"name\":\"Tuning TCP and NIC Offloads for VPS Throughput: SO_SNDBUF, TSO\/GSO, and RTT-Based Buffer Sizing - Virtual Servers VPS Blog\",\"isPartOf\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#website\"},\"datePublished\":\"2026-06-26T02:39:15+00:00\",\"dateModified\":\"2026-09-25T22:04:12+00:00\",\"author\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0\"},\"description\":\"Network tuning advice for VPS hosts is usually a list of sysctl values copied from a 2013 bare-metal guide. Most of it is wrong in two specific ways: it\",\"breadcrumb\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/vps-network-performance-how-to-measure-and-improve-throughput-and-latency\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/virtualserversvps.com\/blog\/vps-network-performance-how-to-measure-and-improve-throughput-and-latency\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/vps-network-performance-how-to-measure-and-improve-throughput-and-latency\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/virtualserversvps.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Tuning TCP and NIC Offloads for VPS Throughput: SO_SNDBUF, TSO\/GSO, and RTT-Based Buffer Sizing\"}]},{\"@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":"Tuning TCP and NIC Offloads for VPS Throughput: SO_SNDBUF, TSO\/GSO, and RTT-Based Buffer Sizing - Virtual Servers VPS Blog","description":"Network tuning advice for VPS hosts is usually a list of sysctl values copied from a 2013 bare-metal guide. Most of it is wrong in two specific ways: it","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\/vps-network-performance-how-to-measure-and-improve-throughput-and-latency\/","og_locale":"en_US","og_type":"article","og_title":"Tuning TCP and NIC Offloads for VPS Throughput: SO_SNDBUF, TSO\/GSO, and RTT-Based Buffer Sizing","og_description":"Tuning TCP and NIC Offloads for VPS Throughput: SO_SNDBUF, TSO\/GSO, and RTT-Based Buffer Sizing","og_url":"https:\/\/virtualserversvps.com\/blog\/vps-network-performance-how-to-measure-and-improve-throughput-and-latency\/","og_site_name":"Virtual Servers VPS Blog","article_published_time":"2026-06-26T02:39:15+00:00","article_modified_time":"2026-09-25T22:04:12+00:00","author":"Virtual-Servers-Vps-Editor","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Virtual-Servers-Vps-Editor","Est. reading time":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/virtualserversvps.com\/blog\/vps-network-performance-how-to-measure-and-improve-throughput-and-latency\/","url":"https:\/\/virtualserversvps.com\/blog\/vps-network-performance-how-to-measure-and-improve-throughput-and-latency\/","name":"Tuning TCP and NIC Offloads for VPS Throughput: SO_SNDBUF, TSO\/GSO, and RTT-Based Buffer Sizing - Virtual Servers VPS Blog","isPartOf":{"@id":"https:\/\/virtualserversvps.com\/blog\/#website"},"datePublished":"2026-06-26T02:39:15+00:00","dateModified":"2026-09-25T22:04:12+00:00","author":{"@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0"},"description":"Network tuning advice for VPS hosts is usually a list of sysctl values copied from a 2013 bare-metal guide. Most of it is wrong in two specific ways: it","breadcrumb":{"@id":"https:\/\/virtualserversvps.com\/blog\/vps-network-performance-how-to-measure-and-improve-throughput-and-latency\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/virtualserversvps.com\/blog\/vps-network-performance-how-to-measure-and-improve-throughput-and-latency\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/virtualserversvps.com\/blog\/vps-network-performance-how-to-measure-and-improve-throughput-and-latency\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/virtualserversvps.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Tuning TCP and NIC Offloads for VPS Throughput: SO_SNDBUF, TSO\/GSO, and RTT-Based Buffer Sizing"}]},{"@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\/518","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=518"}],"version-history":[{"count":3,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/518\/revisions"}],"predecessor-version":[{"id":1221,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/518\/revisions\/1221"}],"wp:attachment":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/media?parent=518"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/categories?post=518"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/tags?post=518"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}