Skip to main content
RunBook Academy

Proxmox VEVI · ZFSZFS architecture

ZFS ARC, ZIL/SLOG, L2ARC

Intermediate⏱ ~16 min

What you'll learn

  • Explain what ARC, ZIL, SLOG, and L2ARC do and when they help
  • Configure a SLOG device for sync-write performance
  • Configure L2ARC for read caching when appropriate
  • Debunk common ZFS myths RAM, ECC

Prerequisites

Verified against Proxmox VE 9.2.4 · Proxmox Backup Server 4.2.5 · Ceph Squid / Tentacle · Debian 13 (Trixie) · Linux kernel 7.0 (PVE 9.2 default) · 2026-08-12

Not yet marked complete on this device.

Why this matters in production

Misconfigured ZFS caching layers are responsible for two production failures: sync writes that are inexplicably slow (no SLOG), and read workloads that thrash (L2ARC misconfigured). Worse, many ZFS myths (“you need 1 GB RAM per TB”) waste budget and lead to over-spec.

The four caches

CacheWhereWhat it doesConfiguration
ARCHost RAMIn-memory read cache; adaptive replacementzfs_arc_max
ZILPool or separateIntent log for sync writesDefault on pool
SLOGSeparate fast deviceBacks the ZIL with low-latency, durable storagezpool add tank log DEVICE
L2ARCSeparate deviceDisk-backed read cachezpool add tank cache DEVICE
flowchart LR
  A[Read request] --> B[ARC hit?]
  B -->|yes| C[RAM: ~1 ms]
  B -->|no| D[L2ARC hit?]
  D -->|yes| E[L2ARC: ~0.1 ms]
  D -->|no| F[Pool: ~5 ms+]
  G[Sync write] --> H[ZIL in pool]
  H --> I[SLOG present?]
  I -->|yes| J[SLOG: ~0.1 ms]
  I -->|no| K[Pool sync write]

ARC — the in-memory read cache

ARC adapts to the workload: hot data stays in RAM.

The default depends on how the node was installed, and this catches people. The upstream ZFS default is 50% of host RAM (62.5% on some versions), which is far too much for a hypervisor that also runs VMs. Since Proxmox VE 8.1, a fresh installation sets ARC to 10% of host memory, clamped to a maximum of 16 GiB — so a node installed recently is already sensible, and a node upgraded from an older release may still be running the upstream default.

Read-only / Safewhat is ARC actually limited to on this node?
cat /sys/module/zfs/parameters/zfs_arc_max
cat /sys/module/zfs/parameters/zfs_arc_min
free -g
arc_summary | head -30

Setting it permanently:

Configuration changelimit ARC to 16 GiB
echo 'options zfs zfs_arc_max=17179869184' > /etc/modprobe.d/zfs.conf

# required when ZFS is the root filesystem
update-initramfs -u -k all
Configuration changeapply it now, without rebooting, to test the effect
echo "$[16 * 1024*1024*1024]" > /sys/module/zfs/parameters/zfs_arc_max

The Proxmox sizing guidance for the other direction — how much ARC a pool actually needs — is 2 GiB base plus 1 GiB per TiB of storage. An 8 TiB pool wants around 10 GiB. That figure and the 10%-of-RAM default disagree on small-memory nodes with large pools, and when they do, the pool sizing is the one to follow.

ZIL and SLOG

The ZIL (ZFS Intent Log) records sync writes before they hit the pool. By default the ZIL lives on the pool itself, which means sync writes compete with the bulk pool for I/O.

A SLOG (Separate Log) device moves the ZIL to a small, low-latency, durable SSD. Sync writes go to the SLOG, then are written to the pool asynchronously.

SLOG deviceSync write latency
None (ZIL on pool)~5 ms+
SATA SSD with PLP~0.5 ms
NVMe with PLP~0.1 ms
zpool add tank log /dev/disk/by-id/nvme-SLOG-Device

L2ARC

L2ARC extends ARC to a disk-backed cache. Useful when:

  • The working set exceeds ARC (RAM).
  • Reads dominate the workload.

L2ARC is not useful when:

  • Writes dominate (L2ARC caches reads only).
  • The ARC is already large enough.

Common myths debunked

MythReality
ZFS needs 1 GB RAM per TB of storageA 2010-era rule of thumb. With modern ARC tuning, 8 GB minimum plus 1 GB per 100 TB if that
ZFS requires ECC RAMZFS detects bit-rot. Without ECC, the host memory can flip a bit and ZFS will use the wrong checksum — but the checksum itself will be wrong and ZFS will report it. ECC helps but is not strictly required
ZFS needs a battery-backed RAID controllerZFS must see raw disks. RAID controllers hide errors
SLOG must be hugeSLOG only needs to hold ~5 seconds of sync writes. A small SSD is fine

Production considerations

Common mistakes

  • Letting ARC grow unbounded.
  • Setting zfs_arc_max below zfs_arc_min and concluding the parameter does not work. Lower the minimum first on large-memory nodes.
  • Forgetting update-initramfs -u -k all on a root-on-ZFS node. The boot-time ARC limit is the old one.
  • Putting swap on a zvol. The failure mode is a deadlock under memory pressure, not slow swapping.
  • Using a consumer SSD as SLOG.
  • Adding L2ARC to a write-heavy workload.
  • Over-provisioning RAM because of “1 GB per TB.”

Key takeaways

  • ARC: in-RAM read cache. Tune zfs_arc_max to leave room for VMs.
  • SLOG: separate device for sync writes. Mandatory for high-sync workloads.
  • L2ARC: optional read cache. Avoid on write-heavy workloads.

Knowledge check

Knowledge check · 4 questions

  1. Q1. What does SLOG do?

  2. Q2. A SLOG device needs power-loss protection, or a power cut can lose writes that ZFS has already acknowledged as durable.

  3. Q3. Why might you limit zfs_arc_max on a Proxmox host?

  4. Q4. On a 512 GiB node you write zfs_arc_max=8589934592 to /etc/modprobe.d/zfs.conf, reboot, and ARC still grows well past 8 GiB. Which explanations are worth checking? Select all that apply.

Passing score: 75%. Answers are checked in this browser.