ZFS Storage & Memory Engineering Takeaways

  • The ARC Sizing Ceiling: By default, TrueNAS SCALE (Linux kernel) caps the ZFS Adaptive Replacement Cache (ARC) at 50% of total host RAM, unlike TrueNAS CORE (FreeBSD) which historically allocated up to 90%.
  • Overriding Linux OOM Penalties: On dedicated storage appliances, restricting ARC to 50% wastes high-speed DRAM. Modifying zfs_arc_max allows safely expanding ARC to 75%–85% of physical memory without triggering Linux Out-Of-Memory (OOM) killer panics.
  • L2ARC Sizing Ratio: Adding an NVMe L2ARC drive without sufficient host RAM degrades performance. Every 1GB of L2ARC consumes approximately 70MB of host ARC memory just to index headers.

When deploying high-throughput network-attached storage or virtualization shared datastores on TrueNAS SCALE, system administrators frequently experience an unexpected performance cliff after migrating from legacy FreeBSD-based TrueNAS CORE: read cache hit rates drop, multi-client SMB transfers exhibit latency jitter, and expensive DDR4/DDR5 system memory sits seemingly idle.

The root cause of this behavior is not hardware degradation; it is the fundamental architectural divergence in memory management between the Linux kernel and the FreeBSD kernel. Understanding how the ZFS Adaptive Replacement Cache (ARC) interacts with the Linux Virtual Memory (VM) subsystem, how to mathematically size host RAM against your storage pool working set, and how to tune ARC kernel parameters is essential to unlocking maximum IOPS from modern enterprise ZFS storage arrays.

Why Does TrueNAS SCALE Cap ARC at 50% of RAM by Default?

Direct Answer: TrueNAS SCALE caps ZFS ARC at 50% of total physical RAM by default because OpenZFS on Linux relies on the Linux kernel memory manager. To prevent ARC memory from competing with Linux Docker containers, KVM virtual machines, and system services—which would trigger the catastrophic Linux Out-Of-Memory (OOM) killer—OpenZFS enforces a conservative 50% ceiling.

In FreeBSD (the operating system underlying TrueNAS CORE), the ZFS filesystem is integrated natively into the kernel’s virtual memory subsystem. When user applications request memory, the FreeBSD kernel can instantaneously reclaim cached ARC pages in sub-microseconds without thread locking. Consequently, TrueNAS CORE safely dedicated up to 90% of host RAM to ARC.

On Linux, however, OpenZFS operates as an external kernel module. The Linux page cache and OpenZFS ARC maintain separate memory allocation accounting. When system memory pressure spikes, the Linux kernel cannot evict OpenZFS ARC buffers as rapidly as its native page cache. If ARC consumed 90% of host RAM and a KVM virtual machine suddenly ballooned its memory allocation, the Linux kernel OOM killer would invoke, aggressively terminating critical host processes like middleware, smbd, or virtual machines to protect kernel stability. To insulate general-purpose users running apps and VMs, TrueNAS SCALE engineers hard-coded a conservative 50% default maximum.

ZFS ARC Sizing Architecture Matrix

The following engineering matrix outlines recommended ARC sizing parameters based on server operational roles and total physical memory footprints:

Server Workload Role Installed Host RAM Default SCALE ARC Cap (50%) Optimized ARC Target (zfs_arc_max) Performance & Stability Rationale
Dedicated Storage Appliance (No VMs/Apps) 64 GB 32 GB 52 GB (80% allocation) Reserves 12GB for Linux OS, SMB, and ZFS metadata; doubles cache capacity.
Dedicated Enterprise SAN/NFS Array 256 GB 128 GB 215 GB (84% allocation) Maximizes random 4K block cache hit rates for Proxmox/VMware iSCSI datastores.
Hybrid Storage + Docker / KVM Host 128 GB 64 GB 64 GB (Keep 50% default) Protects against OOM panics when memory-hungry containers scale under load.
High-Density Petabyte Storage Server 512 GB 256 GB 440 GB (86% allocation) Essential for holding multi-terabyte pool metadata and deduplication tables in RAM.

How to Safely Tune zfs_arc_max in TrueNAS SCALE

If your TrueNAS SCALE server operates primarily as a storage appliance with minimal virtualization overhead, you can safely expand the ARC ceiling using a post-init shell script or TrueNAS Tunables.

The parameter zfs_arc_max is measured in raw bytes. To configure ARC to use 80% of a 128GB RAM system (approximately 103 gigabytes or 110595473408 bytes), execute the following command in the TrueNAS root shell:

# Set ARC maximum to ~103 GB immediately at runtime:
echo 110595473408 > /sys/module/zfs/parameters/zfs_arc_max

# Verify active ARC sizing limits:
arc_summary | grep -E "Target size|Max size"

To persist this configuration across reboots in TrueNAS SCALE, navigate to System Settings > Advanced > Init/Shutdown Scripts, create a new script set to run at Post Init, and enter echo 110595473408 > /sys/module/zfs/parameters/zfs_arc_max. This ensures your high-speed DRAM is fully utilized without being overwritten by TrueNAS system updates.

The L2ARC RAM Indexing Trap

When storage administrators exhaust physical memory slots, they frequently install an inexpensive PCIe NVMe drive as a Level 2 Adaptive Replacement Cache (L2ARC). While an L2ARC can significantly accelerate read throughput for active working sets that exceed physical RAM, deploying an L2ARC without adequate host memory creates a severe architectural bottleneck.

Every single block cached on an L2ARC drive requires a tracking header stored in host RAM. Depending on your pool recordsize (e.g., 16KB for databases vs. 128KB for general media), every 1 gigabyte of L2ARC consumes between 10 megabytes and 70 megabytes of host ARC memory. If you install a massive 4TB NVMe SSD as L2ARC on a server with only 32GB of RAM, the L2ARC header table can consume up to 14GB of your host memory, starving the primary RAM-based ARC and resulting in an overall net decrease in storage IOPS.

The 4:00 PM Actionable TrueNAS SCALE Tuning Playbook

To audit and optimize your TrueNAS SCALE memory allocation today, execute these four tactical steps:

Tactical TrueNAS Memory Optimization Checklist

  1. Audit Active ARC Hit Rate via arcstat: Run arcstat 1 in the TrueNAS shell while executing client workloads. If your ARC hit rate drops below 85% while free system RAM sits above 30GB, your system is throttled by the 50% default cap.
  2. Calculate Safe zfs_arc_max Value: Take your total installed physical memory, subtract 12GB for base OS and service headroom (plus any dedicated VM RAM), and set zfs_arc_max to the remaining byte value.
  3. Configure ARC Metadata Only on High-Volume Pools: For backup pools containing large sequential media files, set zfs set primarycache=metadata poolname to prevent bulk sequential streaming from evicting hot random 4K blocks from memory.
  4. Verify ECC Memory Integrity: Because ZFS relies entirely on RAM for scrub calculations, write aggregation, and metadata management, ensure ECC (Error-Correcting Code) RAM is installed and running without correctable hardware alerts in IPMI.

For more on building high-performance storage architectures and evaluating enterprise hardware, read our comprehensive shootout on Enterprise NAS Shootout: Synology vs TrueNAS Enterprise.