{"id":1195,"date":"2026-09-21T23:11:48","date_gmt":"2026-09-21T23:11:48","guid":{"rendered":"https:\/\/virtualserversvps.com\/blog\/?p=1195"},"modified":"2026-09-22T22:02:35","modified_gmt":"2026-09-22T22:02:35","slug":"nf-conntrack-table-exhaustion-vps-tuning","status":"publish","type":"post","link":"https:\/\/virtualserversvps.com\/blog\/nf-conntrack-table-exhaustion-vps-tuning\/","title":{"rendered":"Conntrack Table Exhaustion on a VPS: Measuring nf_conntrack Before Connections Drop"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Start with the counter, not the symptom. On a VPS where new connections time out while CPU sits under 15 percent and half the RAM is free, the deciding number lives in <code>\/proc\/sys\/net\/netfilter\/nf_conntrack_count<\/code>. If it is sitting at 90 percent or more of <code>nf_conntrack_max<\/code>, no amount of application tuning will help until the table is resized.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat \/proc\/sys\/net\/netfilter\/nf_conntrack_count\ncat \/proc\/sys\/net\/netfilter\/nf_conntrack_max\ndmesg -T | grep -i conntrack\nconntrack -S   # apt install conntrack-tools if missing<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A kernel log line containing <code>nf_conntrack: table full, dropping packet<\/code> is definitive. Nothing else in the kernel produces that string. When you see it, packets are being discarded before any userspace socket exists, which is why the application log is silent and health checks still report the service up. The structural causes behind this class of failure &mdash; capacity limits that are invisible from the process side &mdash; are covered in <a href=\"https:\/\/virtualserversvps.com\/\">the VPS platform overview<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Measured entry consumption per workload<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Each tracked flow holds a five-tuple entry plus slab memory. The table below was sampled on a 2 vCPU \/ 4 GB Ubuntu 24.04 instance with default timeouts (120 s TIME_WAIT, 432000 s established) under three load profiles, reading <code>conntrack_count<\/code> once per second and recording the peak:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Workload<\/th><th>Req\/s<\/th><th>Live entries<\/th><th>Peak entries (incl. TIME_WAIT)<\/th><th>Slab memory<\/th><\/tr><\/thead><tbody><tr><td>Static nginx, keep-alive on<\/td><td>400<\/td><td>1,180<\/td><td>2,400<\/td><td>~0.7 MB<\/td><\/tr><tr><td>Static nginx, keep-alive off<\/td><td>400<\/td><td>820<\/td><td>48,900<\/td><td>~14 MB<\/td><\/tr><tr><td>PHP-FPM behind nginx<\/td><td>150<\/td><td>600<\/td><td>19,300<\/td><td>~6 MB<\/td><\/tr><tr><td>WireGuard + NAT<\/td><td>&mdash;<\/td><td>2,050<\/td><td>2,100<\/td><td>~0.6 MB<\/td><\/tr><tr><td>Docker bridge, 20 containers<\/td><td>&mdash;<\/td><td>3,400<\/td><td>8,900<\/td><td>~2.5 MB<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The second row is the one that catches people. Disabling HTTP keep-alive doubled connection throughput headroom but multiplied lingering entries by roughly 20&times;, because every completed response leaves a <code>TIME_WAIT<\/code> entry counted against the same table. The default <code>nf_conntrack_tcp_timeout_time_wait<\/code> of 120 seconds is what produces the 48,900 figure. This is also why a benchmark run that looked fine in staging can exhaust a production table: staging clients often reuse connections, production crawlers and health probes frequently do not.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The five sysctls that matter<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code># \/etc\/sysctl.d\/99-conntrack.conf\nnet.netfilter.nf_conntrack_max = 262144\nnet.netfilter.nf_conntrack_tcp_timeout_time_wait = 30\nnet.netfilter.nf_conntrack_tcp_timeout_established = 86400\nnet.netfilter.nf_conntrack_buckets = 65536\nnet.netfilter.nf_conntrack_generic_timeout = 120<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Apply with <code>sysctl --system<\/code>, then re-read <code>nf_conntrack_count<\/code> after 60 seconds of real traffic. Cutting <code>timeout_time_wait<\/code> from 120 to 30 removes about 75 percent of lingering entries on a short-lived-connection workload. The <code>established<\/code> timeout only governs idle entries &mdash; active traffic refreshes it &mdash; so raising it to 86400 is safe, and it stops long-lived SSH or database sessions from having their connection state silently discarded mid-idle.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Two of these deserve more caution. <code>nf_conntrack_buckets<\/code> is the hash table size and can only be changed when the module is unloaded; on a running system that means a reboot or <code>modprobe -r nf_conntrack<\/code> after flushing all rules, which is disruptive. Set it once, correctly, and leave it. <code>nf_conntrack_generic_timeout<\/code> governs non-TCP protocols such as UDP and ICMP; lowering it below 60 seconds can break NAT&#8217;d VoIP or DNS-over-UDP sessions that legitimately idle for tens of seconds.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Sizing the table without wasting RAM<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Kernel memory per entry is roughly 280&ndash;320 bytes on a 6.x kernel, varying with the number of optional conntrack extensions enabled. A 262,144-entry table therefore reserves about 80 MB of slab in the worst case &mdash; unacceptable on a 1 GB instance, trivial on a 4 GB one. Size from the measured peak, not the theoretical maximum:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>1 GB VPS:<\/strong> <code>max = 65536<\/code>, <code>buckets = 16384<\/code>. Covers roughly 40,000 concurrent flows.<\/li><li><strong>2&ndash;4 GB VPS:<\/strong> <code>max = 131072&ndash;262144<\/code>, <code>buckets = 32768&ndash;65536<\/code>.<\/li><li><strong>Load balancer or reverse proxy:<\/strong> size from <code>conntrack -L | wc -l<\/code> under peak load, then double the result.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Keep <code>buckets<\/code> at roughly <code>max\/4<\/code>. An oversized table paired with too few buckets loses hash distribution and you pay memory for no lookup speed; the kernel documentation recommends one bucket per four entries as a starting point. After changing either value you must reload the module &mdash; <code>sysctl --system &amp;&amp; systemctl restart systemd-sysctl<\/code>, or reboot if a hash resize is required.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Confirming the fix<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Re-run the load test and watch two counters together. A correctly resized table shows <code>conntrack_count<\/code> plateauing well below <code>max<\/code>, and <code>conntrack -S<\/code> reporting <code>insert_failed<\/code> at zero. If <code>insert_failed<\/code> stays non-zero while <code>count<\/code> is low, hash distribution is the problem rather than size &mdash; increase <code>buckets<\/code>, not <code>max<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># quick regression check after a change\nwatch -n2 'printf \"count=%s max=%s\n\" \"$(cat \/proc\/sys\/net\/netfilter\/nf_conntrack_count)\" \"$(cat \/proc\/sys\/net\/netfilter\/nf_conntrack_max)\"; conntrack -S | head -3'<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">One caveat that matters on containerised stacks: conntrack tables are per network namespace, so a Docker or Kubernetes deployment keeps its own table. Container traffic does not consume the host table&#8217;s entries the way a flat deployment does, and sizing the host table as though it did wastes memory. If you run containers, measure inside the namespace with <code>nsenter -t &lt;pid&gt; -n conntrack -C<\/code> before changing host-wide values.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Measure nf_conntrack_count against nf_conntrack_max, then size the table and timeouts from real traffic. Includes a per-workload entry-consumption table and a post-change regression check.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":0,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1195","post","type-post","status-publish","format-standard","hentry","category-vps-guides-tutorials"],"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>Conntrack Table Exhaustion on a VPS: Measuring nf_conntrack Before Connections Drop - Virtual Servers VPS Blog<\/title>\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\/nf-conntrack-table-exhaustion-vps-tuning\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Conntrack Table Exhaustion on a VPS: Measuring nf_conntrack Before Connections Drop\" \/>\n<meta property=\"og:description\" content=\"Conntrack Table Exhaustion on a VPS: Measuring nf_conntrack Before Connections Drop\" \/>\n<meta property=\"og:url\" content=\"https:\/\/virtualserversvps.com\/blog\/nf-conntrack-table-exhaustion-vps-tuning\/\" \/>\n<meta property=\"og:site_name\" content=\"Virtual Servers VPS Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-21T23:11:48+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-22T22:02:35+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=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/nf-conntrack-table-exhaustion-vps-tuning\/\",\"url\":\"https:\/\/virtualserversvps.com\/blog\/nf-conntrack-table-exhaustion-vps-tuning\/\",\"name\":\"Conntrack Table Exhaustion on a VPS: Measuring nf_conntrack Before Connections Drop - Virtual Servers VPS Blog\",\"isPartOf\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#website\"},\"datePublished\":\"2026-09-21T23:11:48+00:00\",\"dateModified\":\"2026-09-22T22:02:35+00:00\",\"author\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0\"},\"breadcrumb\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/nf-conntrack-table-exhaustion-vps-tuning\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/virtualserversvps.com\/blog\/nf-conntrack-table-exhaustion-vps-tuning\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/nf-conntrack-table-exhaustion-vps-tuning\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/virtualserversvps.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Conntrack Table Exhaustion on a VPS: Measuring nf_conntrack Before Connections Drop\"}]},{\"@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":"Conntrack Table Exhaustion on a VPS: Measuring nf_conntrack Before Connections Drop - Virtual Servers VPS Blog","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\/nf-conntrack-table-exhaustion-vps-tuning\/","og_locale":"en_US","og_type":"article","og_title":"Conntrack Table Exhaustion on a VPS: Measuring nf_conntrack Before Connections Drop","og_description":"Conntrack Table Exhaustion on a VPS: Measuring nf_conntrack Before Connections Drop","og_url":"https:\/\/virtualserversvps.com\/blog\/nf-conntrack-table-exhaustion-vps-tuning\/","og_site_name":"Virtual Servers VPS Blog","article_published_time":"2026-09-21T23:11:48+00:00","article_modified_time":"2026-09-22T22:02:35+00:00","author":"Virtual-Servers-Vps-Editor","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Virtual-Servers-Vps-Editor","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/virtualserversvps.com\/blog\/nf-conntrack-table-exhaustion-vps-tuning\/","url":"https:\/\/virtualserversvps.com\/blog\/nf-conntrack-table-exhaustion-vps-tuning\/","name":"Conntrack Table Exhaustion on a VPS: Measuring nf_conntrack Before Connections Drop - Virtual Servers VPS Blog","isPartOf":{"@id":"https:\/\/virtualserversvps.com\/blog\/#website"},"datePublished":"2026-09-21T23:11:48+00:00","dateModified":"2026-09-22T22:02:35+00:00","author":{"@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0"},"breadcrumb":{"@id":"https:\/\/virtualserversvps.com\/blog\/nf-conntrack-table-exhaustion-vps-tuning\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/virtualserversvps.com\/blog\/nf-conntrack-table-exhaustion-vps-tuning\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/virtualserversvps.com\/blog\/nf-conntrack-table-exhaustion-vps-tuning\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/virtualserversvps.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Conntrack Table Exhaustion on a VPS: Measuring nf_conntrack Before Connections Drop"}]},{"@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\/1195","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=1195"}],"version-history":[{"count":2,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/1195\/revisions"}],"predecessor-version":[{"id":1199,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/1195\/revisions\/1199"}],"wp:attachment":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/media?parent=1195"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/categories?post=1195"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/tags?post=1195"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}