VPS Out of Memory: Diagnose OOM Killer and Add Swap
Your VPS was fine yesterday. Today MySQL keeps dying, SSH takes ten seconds to respond, and every so often a process just vanishes with no error in your app logs. That pattern almost always points to one thing: the server ran out of RAM and the Linux kernel started killing processes to survive. Here's how to confirm it, fix it today, and stop it from happening again.
Symptom: processes dying with no clear reason
Out-of-memory (OOM) situations don't look like a normal crash. There's usually no stack trace, no PHP fatal error, nothing in your WordPress debug log. What you'll actually see is:
- MySQL/MariaDB stops and won't restart cleanly, or restarts silently every few hours
- SSH sessions freeze or take a long time to authenticate
php-fpmworkers get killed mid-request, showing up as random 502s on Nginx or 500s on Apachefree -hshows almost 0 available memory and heavy swap use (or no swap at all)- Server load average looks moderate, but everything still feels frozen
This is different from the high-CPU case where top shows one process pegged at 100%. Here, no single process is necessarily hogging the CPU — the box is just out of physical RAM to hand out.
Step 1: Confirm it's actually an OOM kill
SSH in and check the kernel log first. This is the fastest way to know for sure, instead of guessing:
dmesg -T | grep -i -E "killed process|out of memory"
journalctl -k --since "24 hours ago" | grep -i "out of memory"
If you see a line like this, you've found your answer:
Out of memory: Killed process 18422 (mysqld) total-vm:1245680kB, anon-rss:812340kB
That line tells you exactly which process the kernel sacrificed and roughly how much memory it was holding when it got killed. On most Getwebup VPS plans running WordPress, it's almost always mysqld or a pile of php-fpm workers.
Step 2: Check current memory and swap status
free -h
swapon --show
If swapon --show returns nothing at all, that's a big part of your problem — the server has zero breathing room when RAM fills up, so the kernel goes straight to killing processes instead of paging out idle memory first.
Next, find out who's actually eating the RAM right now:
ps aux --sort=-%mem | head -15
Or, if it's installed, htop gives you a live, sortable view (press Shift+M to sort by memory usage).
Cause: what's actually filling up the RAM
In order of how often we see it on shared VPS plans:
| Cause | Why it happens |
|---|---|
| Too many PHP-FPM workers | pm.max_children set higher than the server can afford, so a traffic spike spawns more workers than there's RAM for |
| MySQL buffer settings too high | innodb_buffer_pool_size left at a default meant for a bigger box (common after downsizing a plan) |
| No swap configured | Nothing to fall back on when RAM briefly spikes, so the kernel kills instead of swapping |
| A runaway backup or import job | mysqldump, a WordPress full-site import, or an unzip of a huge upload running memory-hungry in the foreground |
| Memory leak in a long-running process | A cron script, Node app, or custom daemon that never releases memory and slowly climbs over days |
Fix 1: Add swap space right now (fastest relief)
If you have no swap, this alone will stop most of the killing within minutes, buying you time to fix the root cause properly. On a 1-2GB RAM VPS, a 2GB swap file is a reasonable size:
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
Make it survive a reboot by adding it to /etc/fstab:
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Confirm it's active:
free -h
swapon --show
Then tune how aggressively the kernel uses it. The default swappiness of 60 is too eager for a web server — you want swap as a safety net, not a primary memory tier:
sudo sysctl vm.swappiness=10
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf
Important caveat: swap is a buffer, not a fix. It's slower than RAM by orders of magnitude, so if MySQL starts relying on swap to run its buffer pool, queries will crawl. Treat this as first aid, not the final answer.
Fix 2: Right-size PHP-FPM for your actual RAM
Work out how much memory one PHP process actually uses:
ps -ylC php-fpm8.1 --sort:rss | awk '{print $8/1024 " MB"}'
Then set pm.max_children in your pool config (usually /etc/php/8.1/fpm/pool.d/www.conf) so that max_children × average process size stays comfortably under your total RAM, leaving room for MySQL and the OS:
pm = dynamic
pm.max_children = 8
pm.start_servers = 2
pm.min_spare_servers = 2
pm.max_spare_servers = 4
On a 2GB VPS with a ~40MB average worker size, 8 children is a safer ceiling than the default 50 you sometimes see left over from a template config. Reload after changing:
sudo systemctl restart php8.1-fpm
Fix 3: Bring MySQL's buffer pool in line with available RAM
Check the current setting:
mysql -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';"
A common rule of thumb is 50-60% of total RAM on a dedicated database server, but on a shared WordPress + MySQL VPS, that's too aggressive — leave real headroom for PHP-FPM and the OS. In /etc/mysql/mysql.conf.d/mysqld.cnf:
[mysqld]
innodb_buffer_pool_size = 256M
Restart to apply:
sudo systemctl restart mysql
Prevention: don't get paged for this again
- Always run swap, even on higher-RAM plans — it's cheap insurance against a temporary spike
- Set a memory alert, not just a disk or CPU alert. A simple cron checking
freeoutput and emailing you at 85% usage catches this before the kernel does - Run backups and imports off-peak, and use
--quickwithmysqldumpso it doesn't buffer the whole result set in memory - Re-check PHP-FPM and MySQL sizing any time you upgrade or downgrade your VPS plan — the old config doesn't resize itself
- Watch for slow leaks with a weekly
ps aux --sort=-%memcheck on any custom scripts or Node/Python daemons you run alongside your site
If you're on a Getwebup VPS and want us to check your current memory headroom and PHP-FPM/MySQL sizing, open a ticket from your dashboard — we can pull the numbers and suggest the right plan or config without you needing shell access.
Frequently asked questions
How do I know if my VPS crash was caused by an out-of-memory kill?
Run `dmesg -T | grep -i "out of memory"` or `journalctl -k --since "24 hours ago" | grep -i "out of memory"`. If the kernel killed a process for memory, you'll see a line naming the process (often mysqld or php-fpm) along with how much memory it was using at the time.
Does adding swap fully fix an out-of-memory problem?
No, it buys time. Swap gives the kernel a fallback so it doesn't have to kill a process the moment RAM fills up, but swap is much slower than RAM. If MySQL or PHP starts relying on swap regularly, you need more RAM or lower memory settings, not just a bigger swap file.
How much swap should I add on a small VPS?
A common starting point is swap equal to your RAM size, capped around 2-4GB on most WordPress-sized VPS plans. More than that rarely helps and just delays a problem that's really about needing more RAM or leaner PHP-FPM/MySQL settings.
Why does MySQL keep getting killed instead of a PHP process?
The Linux OOM killer scores processes partly by how much memory they're using, and MySQL's InnoDB buffer pool is often the single largest memory consumer on a small server. If innodb_buffer_pool_size is set too high for the box's actual RAM, MySQL becomes the first target.
Can I check memory usage without SSH access?
If you're on Getwebup managed hosting or a managed VPS plan, open a support ticket and we can pull memory, swap, and process usage for you and recommend the right plan size or config change.