ZFS on Proxmox: Stop Copy-Pasting ARC Tuning From 2014
A database VM got OOM-killed at 03:14 on a Tuesday. The host had 256GB of RAM, twenty VMs, and a zfs_arc_max of 230GB set eighteen months earlier by an admin who read a blog post about "maximizing ZFS performance." The ARC had grown to fill its ceiling, the QEMU processes started swapping, the OOM killer picked the biggest RSS on the box, and a production Postgres instance that was doing nothing wrong got the axe. The fix took four minutes. The outage took six hours to untangle.
This guide is for sysadmins and infrastructure engineers running Proxmox VE with ZFS as their storage backend — whether that's rpool on root or a dedicated pool for VM disks. By the end you'll know exactly how much RAM ARC should get on your node, how to set up snapshots that don't quietly fill your pool, and how to schedule scrubs so you find bit rot before your backups do. No 2014 advice, no hand-waving.
:::note[TL;DR]
- ARC tuning is three numbers:
zfs_arc_max,zfs_arc_min, andzfs_arc_meta_limit. Everything else is noise until you've measured. - Reserve RAM for QEMU and host page cache before setting
zfs_arc_max— the 50% rule is a starting point, not a law. - Snapshots are cheap until blocks diverge; unbounded retention is how pools fill up and
zfs destroybecomes a multi-hour operation. - Scrub monthly via Proxmox's systemd timer, monitor
zpool status, and never scrub a degraded pool. :::
Prerequisites
- Proxmox VE 8.x (PVE 7 works but ships older OpenZFS 2.1 — verify with
zfs --version) - Root or sudo on the node
- An existing ZFS pool (
zpool listshould return something) - Basic familiarity with
zfsandzpoolcommands - Optional but recommended: an alerting path (email, webhook, Prometheus) wired up before you tune anything
Section 1: Why ZFS on Proxmox Is Different From "ZFS on a NAS"
On a TrueNAS box, ZFS owns the machine. On Proxmox, ZFS shares an address space with QEMU, the host kernel, page cache, and every container. That's the entire problem in one sentence. The default Proxmox installer offers ZFS as the root filesystem, and half the people who click "yes" don't realize they've committed to a memory-hungry CoW filesystem competing with their VMs for the same RAM.
Here's what you're actually running:
# Confirm your versions before tuning anything — PVE 7 vs 8 ship different OpenZFS
pveversion -v | head -5
zfs --version
Typical output on a recent PVE 8 install:
proxmox-ve: 8.2.4 (running kernel: 6.8.12-1-pve)
zfs-2.2.4-pve1
zfs-kmod-2.2.4-pve1
OpenZFS 2.2 introduced meaningful changes to ARC behavior and L2ARC eviction versus 2.1, so if you're on PVE 7 with ZFS 2.1, some of the tuning advice below differs. Check the version, don't assume.
1.1 The Memory Budget Reality Check
ZFS needs RAM for three things: the data ARC (read cache), the metadata ARC (dnodes, indirect blocks, spacemaps), and a dirty data buffer for write aggregation. The third one is what people forget — if you push writes faster than the pool can absorb them, ZFS buffers them in RAM, and if ARC is pinned at its ceiling, the write path stalls.
The "50% of RAM" rule of thumb is lazy but not wrong for a dedicated storage box. On a hypervisor it's often wrong in the generous direction — you need headroom for QEMU overhead (typically 1-2GB per VM above the guest's assigned RAM), host page cache, and the kernel itself.
⚠️ TRUNCATED VERSION
This is an abbreviated cross-post. Full article (all config files, architecture diagrams, images): valtersit.com
🛠️ Partner Tools for Developers
ValtersIT curates partner deals for developers and sysadmins — VPS hosting, security tools, monitoring platforms and dev productivity gear. No filler, no affiliate spam.
Top comments (0)