Understanding and Tuning ZFS ARC Cache in TrueNAS

If your TrueNAS system seems to be using far more RAM than any running service would explain, ZFS’s ARC is almost certainly why — and understanding ZFS ARC cache behavior…

cache

If your TrueNAS system seems to be using far more RAM than any running service would explain, ZFS’s ARC is almost certainly why — and understanding ZFS ARC cache behavior prevents the common mistake of treating this as a problem needing to be “fixed” rather than the system working exactly as intended.

What Is ARC?

ARC (Adaptive Replacement Cache) is ZFS’s own RAM-based caching layer, storing frequently and recently accessed data blocks in memory to serve future reads considerably faster than fetching from disk again. This is directly connected to the ECC RAM guide covered earlier — ARC is precisely why ZFS benefits so significantly from more available RAM, and why memory integrity matters specifically for data passing through this cache before being verified against ZFS’s checksums.

Why ARC Uses So Much RAM by Default

By default, ZFS is configured to use up to 50% of system RAM for ARC on many systems (though TrueNAS Scale’s specific defaults vary), which often surprises new users checking system memory usage and seeing seemingly all available RAM consumed. This is intentional — unused RAM provides zero benefit sitting idle, while ARC actively serving cached reads provides genuine, measurable performance improvement, making ZFS’s aggressive default caching a deliberate design choice rather than a bug or memory leak.

Checking Current ARC Usage

arc_summary

This provides a detailed breakdown of ARC size, hit rate, and various internal statistics, giving genuine insight into how effectively your cache is actually performing rather than just its raw size.

Understanding ARC Hit Rate

The ARC hit rate — the percentage of read requests actually served from cache rather than requiring a disk read — is the more meaningful performance indicator than raw ARC size alone. A consistently high hit rate (90%+ is common on well-configured systems with adequate RAM) indicates ARC is genuinely doing its job effectively; a low hit rate despite large ARC size might indicate your working data set genuinely exceeds available cache capacity.

When ARC Sizing Actually Needs Attention

For most homelab TrueNAS deployments, the default ARC behavior works well without manual tuning. Consider adjusting specifically if:

  • TrueNAS is also running Apps (covered in the earlier guide) alongside storage duties, and those apps need guaranteed RAM headroom that ARC’s aggressive default caching might otherwise consume
  • You’re running TrueNAS as a VM with passthrough storage (per the NVMe passthrough guide), where the VM’s allocated RAM needs balancing between ARC and the guest OS’s other needs more deliberately than on bare metal

Setting a Maximum ARC Size

If you need to cap ARC’s RAM usage explicitly, this is configured via a system tunable rather than a typical settings page:

  1. Go to System Settings → Advanced → Tunables.
  2. Add a new tunable: zfs_arc_max, setting the value in bytes (e.g., 8589934592 for an 8GB cap).
  3. Apply and reboot, or use the “On Boot” type if you want this to only apply after restarts rather than immediately.

Balancing ARC Against App Workloads

If you’re running TrueNAS Apps (covered in an earlier guide) that need predictable RAM availability, capping ARC’s maximum size ensures apps aren’t competing with an unconstrained cache for available memory — though remember this tradeoff directly reduces cache effectiveness for your actual storage workloads, so cap conservatively rather than aggressively unless genuinely necessary.

L2ARC: Extending Cache to SSD

For systems with more data than RAM can reasonably cache but wanting cache benefits beyond what ARC alone provides, L2ARC extends the cache layer onto a dedicated SSD, acting as a second-tier cache for data that’s aged out of RAM-based ARC but still accessed somewhat frequently:

  1. Go to your pool’s configuration and add a Cache vdev.
  2. Select a dedicated SSD (ideally one not sharing wear-endurance duties with critical pool data, given the earlier SSD endurance guide’s considerations).

L2ARC is genuinely useful specifically for larger pools with a working set that exceeds available RAM but still benefits from being faster than spinning disk — it’s not automatically beneficial for every setup, and adds its own RAM overhead for tracking L2ARC’s own metadata.

Monitoring ARC Effectiveness Over Time

Beyond one-time arc_summary checks, integrate ARC hit rate monitoring into your existing Grafana/Prometheus setup (covered in an earlier guide) using TrueNAS-specific monitoring exporters, giving you historical visibility into whether cache effectiveness changes as your actual data access patterns evolve over time.

A Practical Recommendation

For most homelab TrueNAS systems with reasonable RAM (16GB+) and workloads not simultaneously competing for that same RAM, leave ARC at its default, unconstrained behavior — the aggressive caching is working as intended and genuinely improving read performance. Only cap it explicitly when you have a specific, concrete reason (competing App workloads, a VM-based TrueNAS deployment with genuinely limited allocated RAM) rather than preemptively “fixing” memory usage that isn’t actually a problem.