Fix Linux Swap Exhaustion: Stop Performance Freezes
Swap exhaustion locks your server? Quick fix: adjust swappiness and add swap space. Here's how to diagnose and fix it without rebooting.
Quick answer
Check swap usage with free -h and swapon --show. If swap is full and the system is thrashing, run sysctl vm.swappiness=10 temporarily. Then add more swap space with fallocate -l 4G /swapfile && mkswap /swapfile && swapon /swapfile. For persistent fix, edit /etc/sysctl.conf and /etc/fstab.
Why swap exhaustion kills performance
I've seen this on Ubuntu 22.04 servers and CentOS 7 boxes alike. When swap is full, the kernel can't page memory out, so it starts killing processes — or worse, it enters a thrashing loop where it spends 90% of CPU time swapping pages in and out. You'll see load averages spike to 50+ on a 4-core machine. The usual trigger? A memory-hungry app like MySQL or Elasticsearch suddenly needing more RAM than available, or a runaway Python script leaking memory.
Fix steps: diagnose and recover
1. Check current swap and memory usage
free -h
swapon --show
vmstat 1 5Look at the si and so columns in vmstat. If they're non-zero for more than a second, you're in thrash territory. free -h will show 0% free swap. That's your smoking gun.
2. Kill the offending process
Run top or htop and sort by memory usage (%MEM). Find the process eating RAM. If it's a non-critical service (like a forgotten Node.js dev server), kill it:
sudo kill -9 <PID>If you can't identify the process, run ps aux --sort=-%mem | head -20. This shows the top 20 memory hogs. If it's a critical service (database, web server), skip to adding more swap instead of killing it.
3. Add temporary swap space
You can add a swap file without rebooting. On a 4GB RAM system, I usually add 2GB to 4GB more swap:
sudo fallocate -l 2G /swapfile2
sudo chmod 600 /swapfile2
sudo mkswap /swapfile2
sudo swapon /swapfile2Verify with swapon --show. The system should calm down within seconds. This saved my tail when a PostgreSQL instance on Ubuntu 20.04 suddenly needed more memory during a heavy dump.
4. Reduce swappiness (low-hanging fruit)
The kernel defaults to swappiness=60, meaning it starts using swap at 40% memory usage. That's insane for modern servers with 16GB+ RAM. Set it to 10 temporarily:
sudo sysctl vm.swappiness=10This tells the kernel to prefer keeping things in RAM until 90% full. Your disk I/O will drop, and load averages will plummet. Test for 10 minutes. If it works, make it permanent.
5. Make fixes permanent
Edit /etc/sysctl.conf and add (or change) this line:
vm.swappiness=10Then add the swap file to /etc/fstab so it survives reboot:
/swapfile2 none swap sw 0 0Apply with sudo sysctl -p and run sudo mount -a to test fstab.
Alternative fixes if the main one fails
If your system is still thrashing after adding swap and setting swappiness low, you're likely out of RAM entirely. Try these:
- Use zRam — compresses memory pages in RAM instead of swapping to disk. On Ubuntu/Debian:
sudo apt install zram-config. On Fedora:sudo dnf install zram-generator. This works great on laptops with SSDs where swap I/O is the bottleneck. - Increase kernel memory limits — For specific apps like MySQL, adjust
innodb_buffer_pool_sizein/etc/mysql/my.cnf. Lower it from 70% of RAM to 50%. - Use early OOM — Install
earlyoom(apt or dnf). It kills processes before the system starts swapping heavily. I've used it on Raspberry Pi 4s with 4GB RAM running multiple services — it works. - Add a swap partition if you have unallocated disk — Use
gdiskorfdiskto create a partition, thenmkswapandswapon. A partition is slightly faster than a file on spinning disks because of contiguous block access.
Prevention tip: set up monitoring and alerting
The real fix is not reacting — it's preventing. I set up a script on all my servers that checks swap usage every 5 minutes and logs it to /var/log/swap_watch.log. If swap usage exceeds 80%, it sends a Slack alert via webhook. Here's a simple one-liner you can run in cron:
*/5 * * * * free | awk '/Swap:/ {if ($3/$2 > 0.8) system("curl -X POST -H 'Content-type: application/json' --data '{"text":"Swap over 80% on $(hostname)"}' https://hooks.slack.com/services/YOUR/WEBHOOK/URL")}'Also, set up a swap file as a safety net during installation. On a 8GB RAM server, I always add a 2GB swap file by default. It rarely gets used, but when a memory leak hits, it buys you time to diagnose before the kernel starts killing processes.
One more thing: if you're running containers (Docker, Kubernetes), set memory limits per container. A single leaky container shouldn't take down the whole host. Use docker run --memory=512m or resources.limits.memory in your pod spec.
Pro tip: On modern SSDs, swap is fast enough for this strategy. On spinning disks, consider using zRam instead — it keeps compressed pages in RAM, avoiding disk I/O entirely.
Was this solution helpful?