Expanding Encrypted Swap and Adding ZRAM to Fix Memory Pressure Stalls

Despite having 32GB of RAM on my Debian Unstable system, I was experiencing random stalls and freezes triggered by memory pressure alerts from psi-notify. Sometimes the system would recover after a few seconds, but often it required a hard reboot. The solution was to expand my existing 4GB encrypted swapfile to 16GB and add ZRAM for compressed swap in RAM.

This builds on my previous guide for setting up encrypted swap on btrfs.

Expand Encrypted Swapfile

First, expand the existing encrypted swapfile from 4GB to 16GB:

# Turn off current swap
sudo swapoff /dev/mapper/swap
sudo systemctl stop systemd-cryptsetup@swap.service

# Remove old swap file
sudo rm /swap/swapfile

# Create new 16GB swap file
sudo btrfs filesystem mkswapfile --size 16g /swap/swapfile

# Reload and restart encrypted swap
sudo systemctl daemon-reload
sudo systemctl start systemd-cryptsetup@swap.service
sudo swapon /dev/mapper/swap

Add ZRAM for Compressed RAM Swap

Install ZRAM tools:

sudo apt update
sudo apt install -y zram-tools

Edit /etc/default/zramswap:

PERCENT=50       # 50% of RAM → ~16 GB compressed swap
ALGO=zstd        # fast and efficient
PRIORITY=100     # higher than disk swap

Enable and start the service:

sudo systemctl enable --now zramswap.service

Tune Swappiness

Lower swappiness so the kernel prefers RAM over swap:

sudo sysctl vm.swappiness=15
echo 'vm.swappiness=15' | sudo tee /etc/sysctl.d/99-swappiness.conf

Verify

Check that both swap devices are active:

sudo swapon --show
cat /proc/swaps

You should see both /dev/mapper/swap (encrypted disk swap) and /dev/zram0 (compressed RAM) listed as active swap devices.

Setting Up a Swap File on BTRFS

With the release of btrfs-progs 6.1 (available in Debian Bookworm), you can create a swap file using the btrfs utility. It will take care of both preallocating the file and marking it as NODATACOW. As BTRFS can’t snapshot a subvolume that contains an active swap file, we will create a new subvolume for the swap file to reside in.

$ sudo btrfs subvolume create /swap
$ sudo btrfs filesystem mkswapfile --size 4g /swap/swapfile
$ sudo swapon /swap/swapfile

To auto-activate the swap file at boot, add the following line to /etc/fstab:

/swap/swapfile none swap defaults 0 0

Encrypted swap file

My entire root filesystem is encrypted, but having unencrypted swap can still lead to sensitive data being inadvertently exposed. The solution is to encrypt the swap file using random keys at boot. Add the following line to /etc/crypttab:

swap /swap/swapfile  /dev/urandom swap,cipher=aes-xts-plain64

And change the swap file location in /etc/fstab to point to /dev/mapper/swap like this:

/dev/mapper/swap none swap defaults 0 0

The new swap file will automatically start upon boot. To start it immediately, run:

$ sudo systemctl daemon-reload
$ sudo systemctl start systemd-cryptsetup@swap.service
$ sudo swapon /dev/mapper/swap

PSI-Notify

Adding a small amount of swap can significantly help in preventing the system from running out of memory. psi-notify can alert you when your running low on memory.

$ sudo apt install psi-notify
$ systemctl --user start psi-notify

Add the following line to ~/.config/psi-notify:

threshold memory some avg10 2.00

You may need to adjust the threshold to ensure it triggers at the right time for your needs. To test memory pressure, you can use the following command:

$ </dev/zero head -c 20G | tail