Swap, swapfiles, and zram

general / published / guide #69 / ≈ 13 min read

Swap is space the kernel can use as an overflow for your RAM. When memory gets tight, Linux takes pages it has not touched in a while — idle bits of programs that are open but doing nothing — and parks them in swap, freeing the fast RAM for whatever you are actually using right now. Swap is not a faster kind of memory and it is not where your programs "run"; it is a holding area for cold pages so that real memory goes to warm ones.

There is a stubborn myth that swap is bad, a relic from the spinning-disk era, something to disable for speed. That is mostly wrong. A small amount of swap lets the kernel reclaim memory it would otherwise have to keep pinned, which on a busy machine makes it more responsive, not less. What changed is where swap lives: modern setups often use zram — compressed swap that stays inside RAM — instead of, or alongside, swap on disk. This guide covers all of it: checking what you have, adding a swapfile, tuning how aggressively swap is used, and setting up zram. If you have not partitioned or mounted disks before, the companion guide Disks: lsblk, fdisk, mkfs, fstab, UUIDs covers the groundwork this one builds on.

Everything here uses tools that ship with the system or are a one-line install, and every one of them is free and open source.

Check what you already have

Before changing anything, look at the current state. The first command everyone reaches for is free, which shows memory and swap totals; the -h flag makes the sizes human-readable:

free -h

The Swap: row tells you the total, used, and free swap. If every number is 0, you have no swap configured at all. To see which swap areas are active — partitions, files, or zram devices — ask swapon (part of util-linux, free software, GPL; it is almost certainly already installed):

swapon --show

That prints one line per active swap area, with its NAME (the device or file), TYPE (partition or file), SIZE, how much is USED, and its PRIO (priority — higher numbers are used first). The kernel exposes the same information as a plain text file, which is handy in scripts:

cat /proc/swaps

Tip: a little swap showing as used even when you have plenty of free RAM is normal and healthy — the kernel proactively moves truly idle pages out so RAM is ready for active work. Used swap is only a worry when it is large and the disk is constantly busy (thrashing), which means you are genuinely out of memory.

Swap partition or swapfile?

Swap can live in two places: a dedicated partition (a slice of the disk with no filesystem, formatted for swap) or a swapfile (an ordinary file inside an existing filesystem). They perform essentially the same; the difference is convenience.

  • A swapfile is the easy, flexible choice. You can create, grow, shrink, or delete it any time without touching the partition table — it is just a file. On older kernels swapfiles had quirks, but on a modern Linux kernel a swapfile on ext4 or xfs is perfectly fine and is what most people should use.
  • A swap partition has to be sized when you partition the disk and is awkward to resize later. Its one genuine advantage: it is the simpler path for hibernation (suspend-to-disk), covered near the end.

Btrfs is the exception that needs care. A swapfile on Btrfs must sit in a file that is not copy-on-write and is never snapshotted, or the kernel will refuse it (or worse, corrupt things). This is a real footgun, so it gets its own recipe below — do not use the plain fallocate recipe on Btrfs.

Warning: on Btrfs, a swapfile must be created NOCOW (no copy-on-write) and kept out of every snapshot. A swapfile inside a subvolume that gets snapshotted can pin huge amounts of space or break swapon. Use the Btrfs-specific steps below, not the universal fallocate one.

Create a swapfile (the universal recipe)

Here is the standard recipe for ext4 and xfs filesystems. Each step has a clear job: allocate the space, lock down its permissions, format it as swap, then switch it on. We will make a 2 GB file at /swapfile — adjust the size to taste.

1. Allocate the file. fallocate (from util-linux, GPL) reserves the space instantly:

# reserve a 2 GB file (works on ext4 and xfs)
sudo fallocate -l 2G /swapfile

2. Lock down the permissions. A swapfile can contain fragments of any program's memory, so only root should be able to read it. The kernel refuses to use a world-readable swapfile, so this step is mandatory:

# owner read/write only
sudo chmod 600 /swapfile

3. Format it as swap. mkswap (util-linux, GPL) writes the swap signature onto the file:

sudo mkswap /swapfile

4. Switch it on. swapon activates it immediately — no reboot needed:

sudo swapon /swapfile

5. Verify. Confirm the kernel picked it up:

swapon --show
free -h

You should now see /swapfile listed as a file-type swap area, and the Swap: total in free should reflect the new size.

Make it permanent (survive a reboot)

Activating with swapon lasts only until the next reboot. To bring the swapfile up automatically every boot, add a line to /etc/fstab — the table that tells the system what to mount and activate at startup.

Warning: a typo in /etc/fstab can stop the machine from booting normally. Back the file up first (sudo cp /etc/fstab /etc/fstab.bak), change only the line you mean to, and after editing run sudo swapon -a — if it activates everything without an error, the swap line is good.

Open the file with a root-aware editor and add the swap line at the end:

# sudoedit picks your editor and saves back as root
sudoedit /etc/fstab

Add exactly this line (fields separated by spaces or tabs; 0 0 means "do not back up, do not fsck"):

/swapfile none swap defaults 0 0

Save, then test the whole fstab without rebooting. swapon -a activates every swap entry in fstab; if it returns silently, the line is correct:

sudo swapon -a
swapon --show

The Btrfs variant (do this instead on Btrfs)

On a Btrfs filesystem the swapfile must be no-copy-on-write and unsnapshotted. The cleanest modern way is the built-in btrfs filesystem mkswapfile, which sets everything up correctly in one step (it needs btrfs-progs, free software, GPL — already present on any Btrfs system):

# creates a NOCOW 2 GB swapfile and runs mkswap on it
sudo btrfs filesystem mkswapfile --size 2G /swapfile
sudo swapon /swapfile

If your btrfs-progs is too old to have mkswapfile, build the file by hand. The key is creating an empty file, marking it NOCOW with chattr +C before any data goes in, and only then allocating it (NOCOW cannot be set on a file that already has content):

# create an empty file, then mark it NOCOW before writing any data
sudo truncate -s 0 /swapfile
sudo chattr +C /swapfile
# now allocate it with dd (fallocate is unreliable for swap on Btrfs)
sudo dd if=/dev/zero of=/swapfile bs=1M count=2048 status=progress
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

Warning: on Btrfs do not use fallocate for a swapfile — a fallocated file can have preallocated extents the kernel rejects for swap. Use btrfs filesystem mkswapfile, or truncate + chattr +C + dd as shown. Also keep the swapfile out of any snapshotted subvolume: a common convention is to put it in its own subvolume, e.g. sudo btrfs subvolume create /swap and place the file at /swap/swapfile.

The fstab line is the same as before (pointing at wherever your file ended up), so the swapfile comes back on every boot.

Remove swap

Turning swap off and deleting the file is the reverse of creating it. Do the steps in this order so the system never references a file that is gone.

1. Deactivate it with swapoff. The kernel moves any pages currently in that swap area back into RAM first, so make sure you have enough free memory (check with free -h):

sudo swapoff /swapfile

2. Remove the fstab line so it does not try to activate at the next boot:

sudoedit /etc/fstab
# delete the line:  /swapfile none swap defaults 0 0

3. Delete the file to reclaim the disk space:

sudo rm /swapfile

To disable a swap partition instead, run swapoff on the partition (e.g. sudo swapoff /dev/sdX2) and remove its fstab line; you would not delete the partition unless you also want the space back via the partition tools.

Tuning: how eagerly Linux uses swap

How readily the kernel moves pages to swap is controlled by a single knob, vm.swappiness, ranging from 0 to 200 (older kernels: 0 to 100). It is not a percentage of RAM — it is a relative preference. A higher value makes the kernel lean toward swapping out application pages sooner; a lower value makes it prefer to drop cached file data and hold application pages in RAM longer.

The default is 60. For a desktop or laptop with a decent amount of RAM, many people lower it to around 10 so interactive apps stay in fast memory and swap is used only under real pressure. See your current value:

cat /proc/sys/vm/swappiness

Change it live (this takes effect immediately but resets at reboot):

sudo sysctl vm.swappiness=10

To make it stick across reboots, drop a small config file into /etc/sysctl.d/ — the directory the system reads at boot for these settings:

# create a persistent setting (the filename just needs to end in .conf)
echo 'vm.swappiness=10' | sudo tee /etc/sysctl.d/99-swappiness.conf
# apply all sysctl.d files now, without rebooting
sudo sysctl --system

Tip: with zram (below), swap lives in fast compressed RAM, so a higher swappiness actually makes sense — Fedora, for instance, ships vm.swappiness=180 on zram-only systems. The right value depends on where your swap is: low for slow disk swap, high for zram.

A related knob, vm.vfs_cache_pressure (default 100), controls how aggressively the kernel reclaims memory used to cache directory and inode lookups. Lowering it slightly (say to 50) keeps that cache around longer, which can speed up file-heavy workloads — but the default is fine for most people, so only touch it if you have a specific reason.

zram: compressed swap in RAM (the modern default)

zram creates a block device that lives entirely in RAM but compresses everything written to it. Used as swap, it gives you a clever trick: when memory gets tight, idle pages are compressed (often to a third of their size or less) and kept in RAM instead of being written to disk. It is far faster than disk swap and it writes nothing to your SSD, which spares its limited write endurance. On low-RAM machines it can be transformative — effectively stretching the RAM you have. This is why Fedora and its derivatives ship zram swap on by default.

The simplest way to set it up across distributions is systemd zram-generator (the zram-generator project, free software, MIT). It reads one small config file and creates the zram swap device automatically at boot.

1. Install it. The package name varies a little by distribution:

# Fedora (often already installed)
sudo dnf install zram-generator

# Arch / Manjaro
sudo pacman -S zram-generator

# Debian / Mint / Ubuntu
sudo apt install systemd-zram-generator

2. Configure it. Create /etc/systemd/zram-generator.conf describing the device. The two settings that matter are how big it may grow and which compression algorithm to use — zstd is the modern default (a great speed-to-ratio balance):

sudoedit /etc/systemd/zram-generator.conf

Put this in it. The zram-size expression below caps the device at half your RAM but no more than 4 GB; ram / 2 alone is a common simpler choice:

[zram0]
zram-size = min(ram / 2, 4096)
compression-algorithm = zstd

3. Activate it. Reload systemd so it notices the new config, then start the generated swap unit (no reboot needed):

sudo systemctl daemon-reload
sudo systemctl start systemd-zram-setup@zram0.service

4. Verify. Two checks. zramctl (from util-linux, GPL) shows the zram device, its algorithm, and how well it is compressing; swapon --show confirms it is in use as swap (notice its high priority — the kernel fills zram before any disk swap):

zramctl
swapon --show

From here on it is automatic — the device comes back on every boot. If you also keep a disk swapfile, that is fine: the kernel uses the higher-priority zram first and only spills to disk under heavier pressure.

Tip: do not confuse zram with zswap. zswap is a kernel feature that acts as a compressed cache in front of your existing disk swap — pages are compressed in RAM and only written to the disk swap area when that cache fills. zram, by contrast, is the swap and never touches the disk. Use one or the other, not both on the same swap: zram for RAM-only compressed swap, zswap to soften an existing disk swap.

Tip: some distributions instead ship zram-tools / zramswap (free software, GPL), which set up zram swap through an /etc/default/zramswap file and a service rather than zram-generator. Either approach gets you the same result — pick whichever your distribution provides; do not run both at once.

How much swap do I need?

There is no single right answer, but some rules of thumb help. These are starting points, not laws:

  • Plenty of RAM (16 GB or more), no hibernation: a small swap is enough — 2 GB to 4 GB of disk swap, or zram sized to half your RAM. It exists mainly to let the kernel offload truly idle pages.
  • Modest RAM (4 GB to 8 GB): swap roughly equal to your RAM is a safe, common choice, and zram is especially worthwhile here.
  • Very little RAM (2 GB or less): swap of 1.5 to 2 times RAM, and definitely set up zram.

If you want hibernation (suspend-to-disk, where the machine writes all of RAM to disk and powers fully off), the rule is firmer: your disk swap must be at least as large as your RAM, because the entire contents of memory are saved there. zram cannot serve this purpose — it lives in the RAM that is being powered down — so hibernation needs a real swap partition or swapfile of size >= RAM. It also needs a resume= kernel parameter (and, for a swapfile, a resume offset) pointing the system at where to read memory back from at power-on. The exact setup varies enough by bootloader and distribution that it is best to follow your distribution's hibernation documentation rather than a generic recipe.

Quick reference

  • free -h / swapon --show / cat /proc/swaps — see current swap.
  • Make a swapfile (ext4/xfs): sudo fallocate -l 2G /swapfile && sudo chmod 600 /swapfile && sudo mkswap /swapfile && sudo swapon /swapfile.
  • Make a swapfile (Btrfs): sudo btrfs filesystem mkswapfile --size 2G /swapfile && sudo swapon /swapfile — NOCOW, unsnapshotted.
  • Persist it: add /swapfile none swap defaults 0 0 to /etc/fstab, then sudo swapon -a.
  • Remove swap: sudo swapoff /swapfile, delete the fstab line, sudo rm /swapfile.
  • Tune: sudo sysctl vm.swappiness=10; persist via /etc/sysctl.d/99-swappiness.conf.
  • zram: install zram-generator, set zram-size + compression-algorithm = zstd in /etc/systemd/zram-generator.conf, then sudo systemctl daemon-reload and start systemd-zram-setup@zram0.service; verify with zramctl.
  • Hibernation needs disk swap >= RAM plus a resume= setup — see your distribution's docs.

← back to index