Swap on a Modern Linux Server: zram, a Swapfile, and When to Use Which

Most cloud images ship with no swap at all, and the first you hear of it is a process getting OOM-killed under a transient memory spike that a few hundred megabytes of headroom would have absorbed.

The reflex fix is “just add swap” — usually a disk swapfile, dropped in once, never tuned. That is better than nothing, but it is not the right answer on a modern server. Disk swap is slow, and the default kernel swappiness was chosen for desktops, not for a box whose job is to serve requests. This is the layered approach I actually deploy: compressed in-RAM swap with zram as the fast first tier, a disk swapfile as cold overflow, and swappiness tuned so the two are used in the right order. The examples target Ubuntu 24.04, but nothing here is Ubuntu-specific.

Why zram first, and a swapfile behind it

zram is a kernel block device that lives in RAM and compresses everything written to it. Used as swap, it means “swapped-out” pages are compressed and kept in memory rather than written to disk. With a modern algorithm you routinely get 2:1 to 4:1 on typical anonymous pages, so a 2 GB zram device might hold 5–7 GB of swapped data while costing a fraction of that in real RAM. The trade is CPU: every page in and out is compressed and decompressed. On any server built in the last decade, that CPU is cheaper than a disk round-trip.

So zram is the fast tier. But zram cannot save you from a genuine, sustained shortfall — once its backing RAM is full, it is full. That is what the disk swapfile is for: cold overflow, given a lower priority so the kernel only reaches for it when zram is exhausted. Two tiers, each doing the job it is good at. Neither is a substitute for sizing the machine correctly, and neither turns a memory leak into anything other than a slower memory leak.

Setting up zram with systemd-zram-generator

Do not script modprobe zram and zramctl by hand — the systemd-zram-generator package turns a small config file into a proper systemd swap unit at boot, which is the same pattern I described for baseline systemd service and timer setup. Install it and write the config:

sudo apt install systemd-zram-generator

# /etc/systemd/zram-generator.conf
sudo tee /etc/systemd/zram-generator.conf >/dev/null <<'EOF'
[zram0]
# Half of RAM, capped at 4 GiB. The device holds several times
# this once pages are compressed, so do not over-size it.
zram-size = min(ram / 2, 4096)
compression-algorithm = zstd
swap-priority = 100
EOF

# Generate and start the unit without a reboot
sudo systemctl daemon-reload
sudo systemctl start /dev/zram0

Three deliberate choices there. The zram-size expression is evaluated against actual RAM at boot, so the same file behaves on a 2 GB and a 32 GB box; min(ram / 2, 4096) is also the generator’s own default, but writing it out makes the intent explicit. zstd gives a markedly better ratio than the kernel’s default lzo-rle for a small CPU cost, which is the right trade on a server. And swap-priority = 100 is high, so zram is always preferred over the disk swapfile.

The swapfile as cold overflow

Now the disk tier, given a deliberately lower priority so it only takes pages zram could not:

# Create a 2 GiB file, lock down its permissions, format and enable
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon --priority 10 /swapfile

# Persist across reboots with a lower priority than zram
echo '/swapfile none swap sw,pri=10 0 0' | sudo tee -a /etc/fstab

The chmod 600 is not optional — swapon will warn about insecure permissions, and a world-readable swap file is a real exposure. fallocate is fine on ext4 and XFS; on Btrfs it is not, and you need a no-copy-on-write file or the dd method instead. The priority is the whole point: pri=10 sits well below zram’s 100, so the kernel drains zram first and only spills to disk when it must.

Swappiness tuned for a server, not a laptop

This is the step “just add swap” always skips. vm.swappiness governs how eagerly the kernel moves anonymous pages to swap versus reclaiming file-backed cache. The default of 60 assumes swap is slow disk, so it errs towards keeping pages in RAM. With zram, swap is fast compressed RAM — the old caution is misplaced, and you want the kernel to lean on it sooner. On kernels 5.8 and later the value can go up to 200; for a zram-fronted server I use 100, which biases towards compressing idle pages while keeping the working set resident.

# /etc/sysctl.d/99-zram.conf
sudo tee /etc/sysctl.d/99-zram.conf >/dev/null <<'EOF'
# zram is fast, so swap more readily than the disk-era default of 60
vm.swappiness = 100
# No read-ahead: zram access is random with no seek penalty
vm.page-cluster = 0
EOF

sudo sysctl --system

vm.page-cluster = 0 matters more than it looks. The default of 3 tells the kernel to read eight pages at a time on a swap-in, which amortises seek latency on a spinning disk. zram has no seek latency, so that read-ahead just wastes CPU decompressing pages nobody asked for. Setting it to zero reads one page at a time. If you keep a general sysctl baseline, fold these in alongside the network and kernel settings covered in sysctl tuning that earns its keep rather than scattering them.

Verify it, and keep it honest

Confirm both tiers are live and in the right order:

# Both devices, with priorities: zram should outrank the swapfile
swapon --show

# Live compression stats: DISKSIZE vs DATA vs COMPR
zramctl

# Confirm the tuning took
sysctl vm.swappiness vm.page-cluster

swapon --show should list /dev/zram0 at priority 100 and /swapfile at 10. In zramctl, watch the ratio between DATA (uncompressed) and COMPR (actual RAM used) — that is your real compression, and it tells you whether the device is sized sensibly. If the swapfile is carrying significant, persistent load while zram sits full, you are not short of swap; you are short of RAM, and the right fix is a bigger box or a lighter workload. Swap buys you headroom against transient spikes. It does not, and should not, paper over a machine that is simply too small for what you have asked it to do.

Free interactive tool

Website compliance checklist

What your site has to do, based on what it actually does

Answer as much or as little as you like — the list builds as you go. Nothing is stored against your name and no email is required.

Most technology problems are not technology problems. They are control problems.

The systems exist. The investment has been made. The question is whether leadership can understand, direct, evidence, and sustain what those systems produce. Find out where control exists — and where it only appears to.