VPS Tutorials
How to Optimize Low-Memory VPS with ZRAM and Swap (2026): Avoid OOM, Lag, and Disk Thrashing
On 1C1G and 1C2G low-memory VPS running WordPress, Docker, or databases, the most common problem isn't insufficient CPU but persistently high memory pressure, which eventually triggers the OOM Killer or swap thrashing. This article explains the differences between ZRAM, swapfile, and zswap, provides directly executable configuration steps for Debian/Ubuntu, and covers swappiness, priorities, monitoring, and rollback methods.

Many cheap VPS are 1C1G or 1C2G. Right after installing the system they seem sufficient, but once Nginx, PHP-FPM, MySQL, Redis, Docker, or scheduled backups run at the same time, memory quickly fills up. Typical symptoms: SSH becomes laggy, the website occasionally returns 502, the database gets killed, Docker containers exit for no reason, and you can still see Out of memory: Killed process in dmesg.
At this point, saying "just add more memory" is of course correct, but not always realistic. For low-cost annual VPS, test machines, small blogs, and lightweight API services, a more practical approach is: use ZRAM to compress cold memory in advance, then keep a small swapfile as a fallback. This won't turn 1GB of memory into 4GB, but it can significantly reduce the probability of OOM and give the system buffer space during short memory spikes.
| Scenario | Recommendation |
|---|---|
| 1GB / 2GB low-memory VPS | Enable ZRAM first, then add a small swapfile as fallback |
| Databases, PHP-FPM occasionally spiking | ZRAM is well suited, reduces OOM caused by short spikes |
| Long-term genuine memory shortage | ZRAM only mitigates; ultimately you still need to reduce configuration usage or upgrade memory |
| Disk I/O already high | Don't rely on a large swapfile, or it will worsen disk thrashing |
| Cheap SSD VPS | A swapfile is fine, but don't treat it as long-term running memory |
Simply put: ZRAM is a "compressed memory buffer," swapfile is a "disk fallback." The former is fast, the latter is slow; the former is better suited for daily buffering on low-memory VPS, the latter for preventing the system from crashing instantly.
Don't rush to change configurations. Use the following commands to confirm the current bottleneck:
free -h
vmstat 1 10
swapon --show
journalctl -k --since "24 hours ago" | grep -i "out of memory\|killed process"
Focus on three things:
availablestays very low for a long time, e.g., only a few dozen MB left.si/soinvmstatcontinuously has values, indicating the system is frequently swapping in and out.- Kernel logs show
Killed process, indicating the OOM Killer has already acted.
If memory only occasionally spikes, ZRAM is well suited; if it's swapping all day long, that's not a tuning problem but a mismatch between application configuration or machine specifications.
Many tutorials mix these concepts together, but they are actually not the same thing.
- ZRAM: Creates a compressed block device in memory; swapped-out data still resides in memory but occupies less space after compression. It's fast and suitable for low-memory VPS.
- Swapfile: Uses a disk file as swap space. Advantages are simplicity and reliability; disadvantages are slowness and easy disk I/O thrashing.
- Zswap: A kernel-level compressed cache, often used as a compression layer before disk swap. It's more low-level, but troubleshooting and explanation costs are higher.
For most Debian/Ubuntu VPS users, the preferred solution is: ZRAM + small swapfile. This provides both speed and a final fallback.
The simplest way on Debian and Ubuntu is to install zram-tools:
sudo apt update
sudo apt install -y zram-tools
Edit the configuration file:
sudo nano /etc/default/zramswap
Recommended to start with a conservative configuration:
ALGO=zstd
PERCENT=75
PRIORITY=100
If you have 1GB of memory, PERCENT=75 will create approximately a 768MB ZRAM device; if 2GB, approximately 1.5GB. Don't set 200% or 300% right away; compression isn't free magic, and CPU and memory management also have costs.
Restart the service and check:
sudo systemctl restart zramswap
zramctl
swapon --show
If you see /dev/zram0 with a priority higher than regular swap, ZRAM is enabled.
Even with ZRAM enabled, I still recommend keeping a small swapfile. The reason is simple: when compressed memory is also full, the system still has a final buffer and won't directly kill processes.
Create a 1GB swapfile:
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
Write to /etc/fstab:
echo '/swapfile none swap sw,pri=10 0 0' | sudo tee -a /etc/fstab
The pri=10 here is key: make its priority lower than ZRAM. The system will use ZRAM first and only fall back to disk swap under greater pressure.
Check priorities:
swapon --show
You should see ZRAM with a higher priority and swapfile with a lower priority.
vm.swappiness determines how aggressively Linux uses swap. Traditional disk swap usually recommends a lower value, such as 10 or 20. But ZRAM is fast, and if set too low, the system may still wait until near OOM before swapping out.
For low-memory VPS with ZRAM enabled, I recommend starting like this:
sudo sysctl vm.swappiness=100
Write persistent configuration:
echo 'vm.swappiness=100' | sudo tee /etc/sysctl.d/99-zram-swap.conf
sudo sysctl --system
If you find the CPU is weak and compression adds extra burden, you can lower to 60; if memory spikes are frequent and CPU still has headroom, try 120. Don't blindly copy a fixed value; the key is to observe the actual state after changes.
After configuration, use the following command groups to observe for 1-2 days:
free -h
zramctl
swapon --show
vmstat 1 10
journalctl -k --since "24 hours ago" | grep -i "out of memory\|killed process"
Under normal circumstances, you want to see:
- Compressed data in
zramctl, but not persistently 100% full. swapfilerarely used, or only briefly used during spikes.si/soinvmstatnot persistently spiking.- No OOM Killer records in the last 24 hours.
If ZRAM is persistently full and swapfile also keeps growing, the machine is genuinely insufficient. Continuing to add swap will only make the website slower; the correct approach is to reduce service usage or upgrade the configuration.
Wrong. Configuring 8GB swap on a low-memory VPS often just turns "processes being killed" into "the whole machine freezing." Swap is a fallback, not memory expansion.
ZRAM is a compressed swap device in memory that disappears after reboot, but swap was never persistent storage anyway. Your business data should be on disk, in databases, and in backups, not relying on swap.
ZRAM only mitigates pressure; it cannot replace application tuning. MySQL buffer, PHP-FPM workers, Node.js memory limits, and Docker container limits all need to be considered together.
| VPS Memory | ZRAM Size | swapfile | swappiness | Notes |
|---|---|---|---|---|
| 512MB | 50%-75% RAM | 512MB | 80-100 | Only suitable for very lightweight services |
| 1GB | 75%-100% RAM | 1GB | 100 | Recommended starting point for small blogs, lightweight APIs |
| 2GB | 75% RAM | 1-2GB | 80-100 | Suitable for WordPress + small database |
| 4GB+ | 50% RAM | 1-2GB | 60-100 | More for peak prevention, not a core dependency |
If you find CPU usage increases or latency worsens after configuration, you can roll back directly.
Disable ZRAM:
sudo systemctl stop zramswap
sudo systemctl disable zramswap
Delete swapfile:
sudo swapoff /swapfile
sudo rm /swapfile
sudo nano /etc/fstab
Just remove the /swapfile line from /etc/fstab.
For low-memory VPS, the most reliable strategy is not simply "enable swap" but a three-step approach:
- Use ZRAM to handle short-term memory spikes.
- Use a small swapfile as the final fallback.
- Use service-level limits to control the resident usage of MySQL, PHP-FPM, and Docker.
If you only occasionally OOM, this solution is usually very effective; if your business relies on swap to stay alive long-term, it's time to upgrade memory or split the database. The goal of optimization is not to make the VPS never report errors, but to make it stable, observable, and rollback-capable under reasonable load.