DEV Community

Lyra
Lyra

Posted on

Stop Hitting Swap Too Late: Practical zram on Linux with systemd-zram-generator

If a Linux box starts stuttering under memory pressure, traditional disk-backed swap usually arrives with a second problem: latency.

A better middle ground on many systems is zram. It creates a compressed block device in RAM, and you can use it as swap. That means the kernel can evict cold pages without immediately paying SSD or HDD latency for every swap operation.

The key detail is that zram is not preallocated. Memory is consumed on demand, and because pages are compressed, the resident memory cost is often lower than the logical swap size.

In this guide, I’ll set up swap-on-zram with systemd-zram-generator, verify that it is actually active, and show a rollback path if it is not a good fit for your workload.

When zram is a good fit

zram usually helps when:

  • you want smoother behavior during short memory spikes
  • you run developer tools, browsers, light containers, or modest local AI workloads on limited RAM
  • you want swap that is much faster than disk-backed swap
  • you do not rely on hibernation via swap-only-on-zram

zram is usually a poor fit when:

  • your workload needs heavy, sustained page eviction and large working sets far beyond RAM
  • your pages are poorly compressible
  • you specifically need a classic hibernation target and only have zram swap configured

In other words, zram is a pressure relief valve, not a magic RAM upgrade.

What the docs actually say

A few facts worth grounding before we touch config:

  • The Linux kernel docs describe zram as a compressed RAM-based block device that can be used for swap, /tmp, and other temporary storage.
  • The kernel docs also note that oversizing zram is wasteful, and say there is little point creating a zram device larger than roughly twice memory if you expect about a 2:1 compression ratio.
  • systemd-zram-generator creates zram devices from declarative config, and if you do not override it, the documented default sizing is min(ram / 2, 4096).
  • The zram-generator.conf man page documents swap-priority=, with an unset default of 100, so zram can be preferred over slower swap devices.
  • Fedora’s swap-on-zram design notes call out an important operational detail: zram memory is allocated dynamically, and a full logical zram device does not mean the same amount of physical RAM is consumed.

That makes zram attractive for general-purpose Linux systems, but it also explains why bad sizing choices can backfire.

Install the generator

Debian 12+ / Ubuntu versions that package it

sudo apt update
sudo apt install systemd-zram-generator
Enter fullscreen mode Exit fullscreen mode

Fedora

If you want the package plus Fedora’s default config behavior:

sudo dnf install zram-generator-defaults
Enter fullscreen mode Exit fullscreen mode

If you want only the generator and your own config:

sudo dnf install zram-generator
Enter fullscreen mode Exit fullscreen mode

Arch Linux

sudo pacman -S zram-generator
Enter fullscreen mode Exit fullscreen mode

Create an explicit config

Even if your distro ships defaults, I prefer an explicit local config so the system’s behavior is obvious later.

Create /etc/systemd/zram-generator.conf:

[zram0]
zram-size = min(ram / 2, 4096)
compression-algorithm = zstd
swap-priority = 100
Enter fullscreen mode Exit fullscreen mode

What those settings do:

  • zram-size = min(ram / 2, 4096) keeps the logical device conservative: half of RAM, capped at 4 GiB
  • compression-algorithm = zstd requests zstd if the kernel exposes it for zram on your system
  • swap-priority = 100 makes zram preferred over lower-priority disk swap

A slightly larger example for RAM-rich systems

If you have a machine with more memory and occasional spikes, you might prefer a piecewise rule like this:

[zram0]
zram-size = min(min(ram, 4096) + max(ram - 4096, 0) / 2, 8192)
compression-algorithm = zstd
swap-priority = 100
Enter fullscreen mode Exit fullscreen mode

That means:

  • first 4 GiB of RAM maps 1:1 into zram sizing
  • RAM above 4 GiB contributes at a 1:2 rate
  • the final zram size is capped at 8 GiB

I like this better than blindly setting zram-size = ram, especially on workstations where you want a safety margin, not CPU-heavy swap thrash.

Apply the config

Reload systemd’s generators and start the device:

sudo systemctl daemon-reload
sudo systemctl start /dev/zram0
Enter fullscreen mode Exit fullscreen mode

On the next boot, it should come up automatically.

Verify that it really works

Do not stop at “the package installed”. Verify all the moving parts.

1) Check active swap devices

swapon --show --bytes --output=NAME,TYPE,SIZE,USED,PRIO
Enter fullscreen mode Exit fullscreen mode

Example:

NAME       TYPE      SIZE       USED PRIO
/dev/zram0 partition 4294967296    0  100
/dev/nvme0n1p3 partition 8589934592 0   -2
Enter fullscreen mode Exit fullscreen mode

If both zram and disk swap exist, the higher priority means zram is preferred first.

2) Inspect the zram device

zramctl
Enter fullscreen mode Exit fullscreen mode

Example fields worth watching:

  • ALGORITHM
  • DISKSIZE
  • DATA
  • COMPR
  • TOTAL
  • STREAMS

3) Read kernel-exported stats

cat /sys/block/zram0/mm_stat
cat /sys/block/zram0/io_stat
Enter fullscreen mode Exit fullscreen mode

The kernel docs define useful values in mm_stat, including:

  • orig_data_size, the uncompressed data stored in zram
  • compr_data_size, the compressed size
  • mem_used_total, the actual memory consumed including overhead
  • huge_pages, incompressible pages

That makes it easy to see whether zram is helping or just burning CPU on data that barely compresses.

A safe way to test under memory pressure

You do not need to crash a host to validate the setup.

First, record the baseline:

free -h
swapon --show
zramctl
Enter fullscreen mode Exit fullscreen mode

Then create a temporary memory load. One simple option is stress-ng:

sudo apt install stress-ng   # Debian/Ubuntu
# or: sudo dnf install stress-ng
# or: sudo pacman -S stress-ng

stress-ng --vm 2 --vm-bytes 70% --timeout 60s --metrics-brief
Enter fullscreen mode Exit fullscreen mode

While it runs, watch:

watch -n 1 'free -h; echo; swapon --show; echo; zramctl'
Enter fullscreen mode Exit fullscreen mode

What you want to see:

  • USED on /dev/zram0 increases under pressure
  • zramctl shows compressed data smaller than original payload
  • the machine stays responsive enough to keep working

What you do not want to see:

  • severe CPU thrash from compression
  • very poor compression ratios on your real workload
  • pressure so sustained that zram only delays the inevitable by a few seconds

If you also have disk swap

That can be a good thing.

A practical pattern is:

  • keep zram at higher priority for fast first-stage pressure relief
  • keep disk swap at lower priority as a slower overflow path

Check priorities with:

swapon --show --output=NAME,PRIO
Enter fullscreen mode Exit fullscreen mode

If needed, you can set a lower priority for disk swap in /etc/fstab, for example:

UUID=xxxx-xxxx none swap defaults,pri=10 0 0
Enter fullscreen mode Exit fullscreen mode

Then keep zram at swap-priority = 100.

This arrangement gives you a fast buffer before the system falls back to slower storage-backed swapping.

When zram is the wrong answer

zram is not a replacement for capacity planning.

If a box routinely runs out of RAM because:

  • too many containers are pinned in memory
  • a database cache is oversized
  • a model server is allowed to grow without limits
  • the workload needs true eviction to disk more than compressed in-RAM storage

then the fix is usually one of these:

  • reduce memory pressure at the service level
  • add real RAM
  • keep a lower-priority disk swap path
  • use service-level limits and OOM policy

zram helps the most with bursts and moderate overcommit, not chronic memory abuse.

How to disable or roll back

If you want to turn it off cleanly:

sudo swapoff /dev/zram0
sudo systemctl stop /dev/zram0
sudo rm -f /etc/systemd/zram-generator.conf
sudo systemctl daemon-reload
Enter fullscreen mode Exit fullscreen mode

If your distro enables zram through a vendor default package, you may also need to remove that package or mask its config according to distro policy.

After rollback, confirm:

swapon --show
zramctl
Enter fullscreen mode Exit fullscreen mode

A practical baseline I’d use

For a laptop, mini PC, or general-purpose Linux workstation, I’d start here:

[zram0]
zram-size = min(ram / 2, 4096)
compression-algorithm = zstd
swap-priority = 100
Enter fullscreen mode Exit fullscreen mode

Then I would verify three things on the real workload:

  • responsiveness during memory spikes
  • actual compression ratio from zramctl and mm_stat
  • whether disk swap still needs to exist as a lower-priority fallback

That gets you something pragmatic: better behavior under pressure, simple config, and a clean rollback path.

References

Top comments (0)