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

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

When zram is a good fit

What the docs actually say

Install the generator

Debian 12+ / Ubuntu versions that package it

Fedora

Arch Linux

Create an explicit config

A slightly larger example for RAM-rich systems

Apply the config

Verify that it really works

1) Check active swap devices

2) Inspect the zram device

3) Read kernel-exported stats

A safe way to test under memory pressure

If you also have disk swap

When zram is the wrong answer

How to disable or roll back

A practical baseline I’d use

References 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. zram usually helps when: zram is usually a poor fit when: In other words, zram is a pressure relief valve, not a magic RAM upgrade. A few facts worth grounding before we touch config: That makes zram attractive for general-purpose Linux systems, but it also explains why bad sizing choices can backfire. If you want the package plus Fedora’s default config behavior: If you want only the generator and your own 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: What those settings do: If you have a machine with more memory and occasional spikes, you might prefer a piecewise rule like this: I like this better than blindly setting zram-size = ram, especially on workstations where you want a safety margin, not CPU-heavy swap thrash. Reload systemd’s generators and start the device: On the next boot, it should come up automatically. Do not stop at “the package installed”. Verify all the moving parts. If both zram and disk swap exist, the higher priority means zram is preferred first. Example fields worth watching: The kernel docs define useful values in mm_stat, including: That makes it easy to see whether zram is helping or just burning CPU on data that barely compresses. You do not need to crash a host to validate the setup. First, record the baseline: Then create a temporary memory load. One simple option is stress-ng: While it runs, watch: What you want to see: What you do not want to see: That can be a good thing. A practical pattern is: Check priorities with: If needed, you can set a lower priority for disk swap in /etc/fstab, for example: Then keep zram at swap-priority = 100. This arrangement gives you a fast buffer before the system falls back to slower storage-backed swapping. zram is not a replacement for capacity planning. If a box routinely runs out of RAM because: then the fix is usually one of these: zram helps the most with bursts and moderate overcommit, not chronic memory abuse. If you want to turn it off cleanly: 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: For a laptop, mini PC, or general-purpose Linux workstation, I’d start here: Then I would verify three things on the real workload: That gets you something pragmatic: better behavior under pressure, simple config, and a clean rollback path. Templates let you quickly answer FAQs or store snippets for re-use. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse

Command

Copy

$ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">update -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install systemd-zram-generator -weight: 600;">sudo -weight: 500;">apt -weight: 500;">update -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install systemd-zram-generator -weight: 600;">sudo -weight: 500;">apt -weight: 500;">update -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install systemd-zram-generator -weight: 600;">sudo -weight: 500;">dnf -weight: 500;">install zram-generator-defaults -weight: 600;">sudo -weight: 500;">dnf -weight: 500;">install zram-generator-defaults -weight: 600;">sudo -weight: 500;">dnf -weight: 500;">install zram-generator-defaults -weight: 600;">sudo -weight: 500;">dnf -weight: 500;">install zram-generator -weight: 600;">sudo -weight: 500;">dnf -weight: 500;">install zram-generator -weight: 600;">sudo -weight: 500;">dnf -weight: 500;">install zram-generator -weight: 600;">sudo -weight: 500;">pacman -S zram-generator -weight: 600;">sudo -weight: 500;">pacman -S zram-generator -weight: 600;">sudo -weight: 500;">pacman -S zram-generator [zram0] zram-size = min(ram / 2, 4096) compression-algorithm = zstd swap-priority = 100 [zram0] zram-size = min(ram / 2, 4096) compression-algorithm = zstd swap-priority = 100 [zram0] zram-size = min(ram / 2, 4096) compression-algorithm = zstd swap-priority = 100 [zram0] zram-size = min(min(ram, 4096) + max(ram - 4096, 0) / 2, 8192) compression-algorithm = zstd swap-priority = 100 [zram0] zram-size = min(min(ram, 4096) + max(ram - 4096, 0) / 2, 8192) compression-algorithm = zstd swap-priority = 100 [zram0] zram-size = min(min(ram, 4096) + max(ram - 4096, 0) / 2, 8192) compression-algorithm = zstd swap-priority = 100 -weight: 600;">sudo -weight: 500;">systemctl daemon-reload -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">start /dev/zram0 -weight: 600;">sudo -weight: 500;">systemctl daemon-reload -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">start /dev/zram0 -weight: 600;">sudo -weight: 500;">systemctl daemon-reload -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">start /dev/zram0 swapon --show --bytes --output=NAME,TYPE,SIZE,USED,PRIO swapon --show --bytes --output=NAME,TYPE,SIZE,USED,PRIO swapon --show --bytes --output=NAME,TYPE,SIZE,USED,PRIO NAME TYPE SIZE USED PRIO /dev/zram0 partition 4294967296 0 100 /dev/nvme0n1p3 partition 8589934592 0 -2 NAME TYPE SIZE USED PRIO /dev/zram0 partition 4294967296 0 100 /dev/nvme0n1p3 partition 8589934592 0 -2 NAME TYPE SIZE USED PRIO /dev/zram0 partition 4294967296 0 100 /dev/nvme0n1p3 partition 8589934592 0 -2 cat /sys/block/zram0/mm_stat cat /sys/block/zram0/io_stat cat /sys/block/zram0/mm_stat cat /sys/block/zram0/io_stat cat /sys/block/zram0/mm_stat cat /sys/block/zram0/io_stat free -h swapon --show zramctl free -h swapon --show zramctl free -h swapon --show zramctl -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install stress-ng # Debian/Ubuntu # or: -weight: 600;">sudo -weight: 500;">dnf -weight: 500;">install stress-ng # or: -weight: 600;">sudo -weight: 500;">pacman -S stress-ng stress-ng --vm 2 --vm-bytes 70% --timeout 60s --metrics-brief -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install stress-ng # Debian/Ubuntu # or: -weight: 600;">sudo -weight: 500;">dnf -weight: 500;">install stress-ng # or: -weight: 600;">sudo -weight: 500;">pacman -S stress-ng stress-ng --vm 2 --vm-bytes 70% --timeout 60s --metrics-brief -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install stress-ng # Debian/Ubuntu # or: -weight: 600;">sudo -weight: 500;">dnf -weight: 500;">install stress-ng # or: -weight: 600;">sudo -weight: 500;">pacman -S stress-ng stress-ng --vm 2 --vm-bytes 70% --timeout 60s --metrics-brief watch -n 1 'free -h; echo; swapon --show; echo; zramctl' watch -n 1 'free -h; echo; swapon --show; echo; zramctl' watch -n 1 'free -h; echo; swapon --show; echo; zramctl' swapon --show --output=NAME,PRIO swapon --show --output=NAME,PRIO swapon --show --output=NAME,PRIO UUID=xxxx-xxxx none swap defaults,pri=10 0 0 UUID=xxxx-xxxx none swap defaults,pri=10 0 0 UUID=xxxx-xxxx none swap defaults,pri=10 0 0 -weight: 600;">sudo swapoff /dev/zram0 -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">stop /dev/zram0 -weight: 600;">sudo rm -f /etc/systemd/zram-generator.conf -weight: 600;">sudo -weight: 500;">systemctl daemon-reload -weight: 600;">sudo swapoff /dev/zram0 -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">stop /dev/zram0 -weight: 600;">sudo rm -f /etc/systemd/zram-generator.conf -weight: 600;">sudo -weight: 500;">systemctl daemon-reload -weight: 600;">sudo swapoff /dev/zram0 -weight: 600;">sudo -weight: 500;">systemctl -weight: 500;">stop /dev/zram0 -weight: 600;">sudo rm -f /etc/systemd/zram-generator.conf -weight: 600;">sudo -weight: 500;">systemctl daemon-reload swapon --show zramctl swapon --show zramctl swapon --show zramctl [zram0] zram-size = min(ram / 2, 4096) compression-algorithm = zstd swap-priority = 100 [zram0] zram-size = min(ram / 2, 4096) compression-algorithm = zstd swap-priority = 100 [zram0] zram-size = min(ram / 2, 4096) compression-algorithm = zstd swap-priority = 100 - 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 - 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 - 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. - 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 - 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 - 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 - USED on /dev/zram0 increases under pressure - zramctl shows compressed data smaller than original payload - the machine stays responsive enough to keep working - 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 - keep zram at higher priority for fast first-stage pressure relief - keep disk swap at lower priority as a slower overflow path - 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 - reduce memory pressure at the -weight: 500;">service level - add real RAM - keep a lower-priority disk swap path - use -weight: 500;">service-level limits and OOM policy - responsiveness during memory spikes - actual compression ratio from zramctl and mm_stat - whether disk swap still needs to exist as a lower-priority fallback - Linux kernel documentation, “Compressed RAM-based block devices (zram)”: https://docs.kernel.org/admin-guide/blockdev/zram.html - systemd-zram-generator README: https://github.com/systemd/zram-generator - zram-generator.conf(5) man page: https://manpages.ubuntu.com/manpages/questing/man5/zram-generator.conf.5.html - Fedora Change proposal, “SwapOnZRAM”: https://fedoraproject.org/wiki/Changes/SwapOnZRAM