Fixing ZFS ARC Consuming All Available RAM on FreeBSD
ZFS looks like it's eating every gigabyte of memory on the system. This is the Adaptive Replacement Cache working as designed — here's how to confirm that and tune it if it's genuinely a problem.
top shows nearly all RAM in use on a ZFS system, with no single process responsible — this is almost always the ARC (Adaptive Replacement Cache), ZFS’s own read cache, doing exactly what it’s designed to do.
Step 1: confirm the memory is actually ARC, not a leak
sysctl kstat.zfs.misc.arcstats.size
vmstat -z | grep -i "arc"
ARC memory shows as “used” in top/free but is immediately reclaimable the moment another process needs it — this is fundamentally different from a memory leak, which never gets reclaimed.
Step 2: check current ARC size limits
sysctl vfs.zfs.arc_max
sysctl vfs.zfs.arc_min
By default, ARC can grow to use most of physical RAM, on the assumption that unused RAM caching disk reads is more useful than unused RAM sitting idle.
Step 3: confirm the system isn’t actually under memory pressure
vmstat -s | grep -i "page"
sysctl vm.stats.vm.v_free_count
If applications are getting killed or swapping heavily, that’s a real problem; if the system is simply “using” RAM for cache while everything runs fine, ARC is working correctly and doesn’t need adjustment.
Step 4: cap ARC size if it needs to coexist with other memory-hungry services
# /boot/loader.conf
vfs.zfs.arc_max="4G"
This requires a reboot to take effect (or sysctl vfs.zfs.arc_max for an immediate but non-persistent change) — useful when running memory-intensive applications (a database, a JVM) alongside ZFS that need a guaranteed memory floor ARC won’t encroach on.
Step 5: verify the new limit takes effect
sysctl vfs.zfs.arc_max
sysctl kstat.zfs.misc.arcstats.size
Why capping ARC isn’t always the right move
Reducing ARC size trades cache-hit performance for memory headroom — on a system where ZFS is the primary workload, a smaller ARC means more disk reads and worse performance. Capping it is the right fix specifically when other processes need guaranteed memory, not a general “fix” for memory usage that’s actually cache doing its job correctly.