{"id":1355,"date":"2026-10-10T22:33:13","date_gmt":"2026-10-10T22:33:13","guid":{"rendered":"https:\/\/virtualserversvps.com\/blog\/?p=1355"},"modified":"2026-10-10T22:33:13","modified_gmt":"2026-10-10T22:33:13","slug":"tuning-linux-oom-killer-oom-score-systemd-oomd-vps-memory-pressure","status":"publish","type":"post","link":"https:\/\/virtualserversvps.com\/blog\/tuning-linux-oom-killer-oom-score-systemd-oomd-vps-memory-pressure\/","title":{"rendered":"Tuning the Linux OOM Killer and systemd-oomd on Memory-Pressured VPS Instances"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">The OOM killer is the least understood thing on a small VPS. It fires, kills your database instead of the runaway process, and the only trace is a line in the journal you scroll past. Getting it right is not about &#8220;disabling&#8221; it &#8212; it is about controlling which process dies, and doing it before the kernel has to make a knife-edge decision. This guide tunes both the classic kernel OOM killer and the newer <code>systemd-oomd<\/code>, which work together and can also fight each other if misconfigured.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">These techniques matter most on a <a href=\"https:\/\/virtualserversvps.com\/\">small VPS where RAM is the binding constraint<\/a>, and they complement the memory-reclaim tuning documented on the <a href=\"https:\/\/virtualserversvps.com\/\">main site<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Understand the two layers<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">There are two independent mechanisms:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Kernel OOM killer<\/strong> &#8212; fires when the kernel is genuinely out of reclaimable memory. It picks a victim by <code>oom_score<\/code>. This is a last resort that you cannot fully prevent, only steer.<\/li><li><strong>systemd-oomd<\/strong> &#8212; watches PSI (pressure stall information) and kills a whole cgroup <em>before<\/em> the kernel OOM killer activates. It targets the cgroup that is causing pressure, which is usually a much better choice than the kernel&#8217;s heuristic.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Check whether oomd is running before tuning anything:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>systemctl status systemd-oomd\ncat \/proc\/pressure\/memory<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>\/proc\/pressure\/memory<\/code> is the same signal oomd acts on: <code>some avg10<\/code> is the percentage of time at least one task stalled on memory; <code>full avg10<\/code> is time <em>everything<\/em> stalled. Sustained <code>full<\/code> above a few percent means you are in the danger zone.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Steering the kernel OOM killer<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Every process has an <code>oom_score_adj<\/code> from -1000 (never kill) to +1000 (kill first). The kernel computes an <code>oom_score<\/code> from memory usage and then biases it by this value. Protect your critical database:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># For a systemd service:\n[Service]\nOOMScoreAdjust=-500\n\n# At runtime, by PID:\necho -500 &gt; \/proc\/$(pgrep -f postgres)\/oom_score_adj\ncat \/proc\/$(pgrep -f postgres)\/oom_score   # observe the effect<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Do not use -1000. That makes the process unkillable, and if it is the thing eating memory the kernel will instead kill something you care about even more, or wedge entirely. Reserve -1000 for nothing on a general-purpose box; -500 to -900 is the useful range. Symmetrically, add a positive adjustment to batch jobs whose death is cheap:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>[Service]\nOOMScoreAdjust=500<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Controlling overcommit<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>vm.overcommit_memory = 0     # heuristic (default)\nvm.overcommit_ratio = 50\nvm.min_free_kbytes = 65536<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Leave <code>overcommit_memory=0<\/code> on a general VPS. Setting it to 1 (&#8220;always overcommit&#8221;) is a copy-paste favourite for Redis, but unless you actually need it for forking under a large dataset, it just removes the kernel&#8217;s early sanity check and makes the eventual OOM sharper. Raising <code>min_free_kbytes<\/code> reserves a small safety margin that keeps reclaim steady instead of letting the kernel reach a cliff.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Using cgroups v2 to bound the damage<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The real fix is not letting any single service be able to eat the whole box. With cgroups v2, memory limits are enforced per cgroup, and an over-limit cgroup is reclaimed, then OOM-killed <em>within itself<\/em> &#8212; sparing everything else:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>[Service]\nMemoryHigh=800M\nMemoryMax=1G\nMemorySwapMax=256M\nMemoryAccounting=yes<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>MemoryHigh<\/code> is a soft throttle &#8212; the kernel reclaims aggressively and applies pressure to the cgroup, which the application can notice and back off. <code>MemoryMax<\/code> is the hard wall. Setting <code>MemoryHigh<\/code> a little below <code>MemoryMax<\/code> gives the workload a chance to shed memory before it is killed. Verify enforcement with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>systemctl show myapp.service -p MemoryCurrent -p MemoryMax\ncat \/sys\/fs\/cgroup\/system.slice\/myapp.service\/memory.events<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>memory.events<\/code> file counts <code>high<\/code>, <code>max<\/code>, and <code>oom<\/code> hits &#8212; this is how you know whether your limits are doing anything or are set too generously to ever bind.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Configuring systemd-oomd<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>[OOM]\nSwapUsedLimit=90%\nDefaultMemoryPressureLimit=60%\nDefaultMemoryPressureDurationSec=20s\nManagedOOMSwap=auto\nManagedOOMMemoryPressure=auto<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>DefaultMemoryPressureLimit=60%<\/code> with a 20-second duration means oomd kills a cgroup only after it has sustained 60% pressure for 20 seconds &#8212; long enough to avoid killing things during transient spikes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Per-unit overrides on the units <em>you care about<\/em> are more important than global settings:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Protect the database\n[Service]\nManagedOOMMemoryPressure=kill\nManagedOOMSwap=kill\n\n# Protect a service entirely from oomd\n[Service]\nManagedOOMMemoryPressure=avoid\nManagedOOMSwap=avoid<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This is the key insight: <code>avoid<\/code> and <code>kill<\/code> control who oomd <em>picks<\/em>. Put <code>avoid<\/code> on your database and web tier, and let oomd target the containers or batch jobs that can safely die. Without this, oomd picks the cgroup with the highest pressure, which may well be the database that is merely a victim of another process thrashing the page cache.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Avoiding the oomd\/KSM\/swap interaction trap<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If you have disabled swap entirely, oomd&#8217;s swap-limiting heuristics have nothing to act on and it relies purely on PSI, which is fine &#8212; but the kernel&#8217;s own reclaim then has no escape valve, so latency during pressure gets much worse before the kill. A small swap file (even 1-2 GB on NVMe, with low <code>vm.swappiness<\/code>) gives reclaim somewhere to put cold pages and makes the whole system far more predictable. Verify that oomd is not fighting a low <code>vm.swappiness<\/code> by watching <code>\/proc\/pressure\/memory<\/code> after the change &#8212; if <code>full avg10<\/code> falls, the combination is working.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Testing that your configuration works<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Do not wait for a production OOM to learn whether your tuning is right. Force memory pressure deliberately with a controlled allocator and watch which process dies:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># In a temporary cgroup, allocate until killed\nsystemd-run --scope -p MemoryMax=200M \\\n  python3 -c \"a=[]\nwhile True: a.append(bytearray(10*1024*1024))\"\njournalctl -k --since \"-2min\" | grep -i oom\ndmesg | grep -i 'killed process'<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The allocation should be killed inside its own cgroup and nothing else should die. If your database gets killed instead, the <code>oom_score_adj<\/code> or oomd <code>avoid<\/code> setting is not applied &#8212; re-check that the unit was reloaded with <code>systemctl daemon-reload<\/code> and the service restarted, because these values are read at process start, not on every access.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Monitoring before it fires<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Alert on <code>memory.psi.full.avg10<\/code> in node-exporter rather than on the OOM event &#8212; by the time the OOM message appears you have already lost the service. A threshold alert on sustained <code>full<\/code> pressure above 5% gives you minutes of warning to investigate, which is usually enough to fix the leak that is causing it.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The OOM killer is the least understood thing on a small VPS. It fires, kills your database instead of the runaway process, and the only trace is a line in&#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":[1],"tags":[],"class_list":["post-1355","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>Tuning the Linux OOM Killer and systemd-oomd on Memory-Pressured VPS Instances - Virtual Servers VPS Blog<\/title>\n<meta name=\"description\" content=\"The OOM killer is the least understood thing on a small VPS. It fires, kills your database instead of the runaway process, and the only trace is a line in\" \/>\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\/tuning-linux-oom-killer-oom-score-systemd-oomd-vps-memory-pressure\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Tuning the Linux OOM Killer and systemd-oomd on Memory-Pressured VPS Instances\" \/>\n<meta property=\"og:description\" content=\"Tuning the Linux OOM Killer and systemd-oomd on Memory-Pressured VPS Instances\" \/>\n<meta property=\"og:url\" content=\"https:\/\/virtualserversvps.com\/blog\/tuning-linux-oom-killer-oom-score-systemd-oomd-vps-memory-pressure\/\" \/>\n<meta property=\"og:site_name\" content=\"Virtual Servers VPS Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-10T22:33:13+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\/tuning-linux-oom-killer-oom-score-systemd-oomd-vps-memory-pressure\/\",\"url\":\"https:\/\/virtualserversvps.com\/blog\/tuning-linux-oom-killer-oom-score-systemd-oomd-vps-memory-pressure\/\",\"name\":\"Tuning the Linux OOM Killer and systemd-oomd on Memory-Pressured VPS Instances - Virtual Servers VPS Blog\",\"isPartOf\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#website\"},\"datePublished\":\"2026-10-10T22:33:13+00:00\",\"author\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0\"},\"description\":\"The OOM killer is the least understood thing on a small VPS. It fires, kills your database instead of the runaway process, and the only trace is a line in\",\"breadcrumb\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/tuning-linux-oom-killer-oom-score-systemd-oomd-vps-memory-pressure\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/virtualserversvps.com\/blog\/tuning-linux-oom-killer-oom-score-systemd-oomd-vps-memory-pressure\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/tuning-linux-oom-killer-oom-score-systemd-oomd-vps-memory-pressure\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/virtualserversvps.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Tuning the Linux OOM Killer and systemd-oomd on Memory-Pressured VPS Instances\"}]},{\"@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 the Linux OOM Killer and systemd-oomd on Memory-Pressured VPS Instances - Virtual Servers VPS Blog","description":"The OOM killer is the least understood thing on a small VPS. It fires, kills your database instead of the runaway process, and the only trace is a line in","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\/tuning-linux-oom-killer-oom-score-systemd-oomd-vps-memory-pressure\/","og_locale":"en_US","og_type":"article","og_title":"Tuning the Linux OOM Killer and systemd-oomd on Memory-Pressured VPS Instances","og_description":"Tuning the Linux OOM Killer and systemd-oomd on Memory-Pressured VPS Instances","og_url":"https:\/\/virtualserversvps.com\/blog\/tuning-linux-oom-killer-oom-score-systemd-oomd-vps-memory-pressure\/","og_site_name":"Virtual Servers VPS Blog","article_published_time":"2026-10-10T22:33:13+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\/tuning-linux-oom-killer-oom-score-systemd-oomd-vps-memory-pressure\/","url":"https:\/\/virtualserversvps.com\/blog\/tuning-linux-oom-killer-oom-score-systemd-oomd-vps-memory-pressure\/","name":"Tuning the Linux OOM Killer and systemd-oomd on Memory-Pressured VPS Instances - Virtual Servers VPS Blog","isPartOf":{"@id":"https:\/\/virtualserversvps.com\/blog\/#website"},"datePublished":"2026-10-10T22:33:13+00:00","author":{"@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0"},"description":"The OOM killer is the least understood thing on a small VPS. It fires, kills your database instead of the runaway process, and the only trace is a line in","breadcrumb":{"@id":"https:\/\/virtualserversvps.com\/blog\/tuning-linux-oom-killer-oom-score-systemd-oomd-vps-memory-pressure\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/virtualserversvps.com\/blog\/tuning-linux-oom-killer-oom-score-systemd-oomd-vps-memory-pressure\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/virtualserversvps.com\/blog\/tuning-linux-oom-killer-oom-score-systemd-oomd-vps-memory-pressure\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/virtualserversvps.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Tuning the Linux OOM Killer and systemd-oomd on Memory-Pressured VPS Instances"}]},{"@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\/1355","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=1355"}],"version-history":[{"count":1,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/1355\/revisions"}],"predecessor-version":[{"id":1357,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/1355\/revisions\/1357"}],"wp:attachment":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/media?parent=1355"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/categories?post=1355"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/tags?post=1355"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}