ZFS RAM (ARC), SLOG & Special VDEV Calculator
Estimates ZFS metadata from the data stored, the record size and the average file size. Each file needs a 512-byte dnode and a 128-byte directory entry, and a file of several records keeps 128-byte block pointers in 128 KiB indirect blocks padded to whole sectors. The special vdev stores two copies and the ARC caches one. A dedup table adds 320 bytes a block, and the SLOG holds 5 to 15 seconds of sync writes, up to ZFS's write-log limit.
Enter how much data a pool will hold, its record size and its average file size, and the calculator estimates the metadata ZFS writes: the space it takes on a special vdev, its share of the data and the ARC needed to keep it all in memory. It adds the RAM a dedup table needs at 320 bytes a block, and sizes a SLOG from the speed sync writes arrive at. The defaults describe a media server holding 48 TB of 16 MiB files at the default 128 KiB record size. They need 97.41 GB of special vdev, 0.203 percent of the data, and 53.36 GiB of RAM: 45.36 GiB of ARC for metadata plus 8 GiB for the system. Deduplication would add a 109.14 GiB table. Over 10 GbE the SLOG needs 8.59 GB, the most ZFS will log with that much RAM.
How the metadata is worked out
ZFS finds every block of a file through a 128-byte block pointer. A file that fits in one record keeps its only pointer in its dnode, the 512-byte structure that describes the file. A file of several records keeps its pointers in indirect blocks of 128 KiB, 1,024 pointers each, and a file of more than 1,024 records needs another level of indirect blocks above those. Every file also has a name in its directory. A small directory stores each name in a 64-byte entry, while a large one uses at least three 24-byte chunks of a 16 KiB leaf that splits in two when it fills, so the calculator counts 128 bytes a name.
ZFS compresses metadata and stores it in whole sectors. An indirect block holding a few pointers still takes a full sector, and one that would not save at least an eighth of its 128 KiB is stored whole. The calculator counts each pointer at its full 128 bytes and the empty rest of the block as free. Real pointers compress, because each has room for two more copies of the block that usually sits empty, which is why 32 of them fit one 4 KiB sector despite the small header LZ4 adds. The default redundant_metadata=all property writes one extra copy of all metadata, so the special vdev stores everything twice while the ARC caches one compressed copy:
metadata = files × (512 + 128 + indirect bytes per file) × 2
The dedup table holds an entry for every block, about 320 bytes in memory each by Oracle's rule. RAM to install adds the ARC for metadata, the dedup table when deduplication is on, and your allowance for the system. A SLOG has to hold the sync writes ZFS has not yet committed to the pool:
SLOG = min(write rate × 5 s × transaction groups, 2 × min(RAM ÷ 10, 4 GiB))
A worked example with the defaults
48 TB of 16 MiB files is 2,861,022.95 files of 128 blocks each at a 128 KiB record size. Each file's 128 pointers fill 16,384 bytes of one indirect block, exactly four 4 KiB sectors, so with its dnode and its name a file carries 17,024 bytes of metadata. Across the pool that is 45.36 GiB, which the ARC caches as it is stored, and 97.41 GB on the special vdev once it is written twice, 0.203 percent of the data. Indirect blocks account for 93.75 GB of that, dnodes for 2.93 GB and names for 0.73 GB. With 8 GiB for everything else, the machine wants 53.36 GiB of RAM.
The pool holds about 366 million blocks, so a dedup table would take 109.14 GiB and raise the RAM to 162.5 GiB. With 53.36 GiB installed, ZFS keeps at most 4 GiB of dirty data and logs at most twice that, 8.59 GB, which a 10 GbE link fills in 6.87 seconds, so the SLOG never needs the 18.75 GB that 15 seconds of 10 GbE would suggest.
Where the ARC, the intent log and special vdevs came from
ZFS's cache starts from ARC, which Nimrod Megiddo and Dharmendra Modha of IBM's Almaden Research Center presented at the FAST conference in 2003. It balances recently used pages against frequently used ones and tunes that balance itself as the workload changes. The OpenZFS source credits the paper and lists where ZFS departs from it: blocks in use cannot be evicted, the cache grows and shrinks with memory pressure, and blocks vary in size.
Oracle's table of pool versions dates the other parts. Ditto blocks, extra copies of metadata, arrived in pool version 2, separate intent log devices in version 7 and deduplication in version 21, in Solaris development builds 38, 68 and 128. OpenZFS 0.8.0, released on 23 May 2019, added allocation classes, which let a pool give a few fast SSDs to metadata and other blocks it reads often, as special vdevs, or to the dedup table, as dedup vdevs. OpenZFS 2.1.6 in October 2022 added a throttle on logged write data, 2.2.0 in October 2023 dropped the old cap that kept metadata to 75 percent of the ARC, and 2.3.0 on 14 January 2025 brought fast dedup, whose new tables keep a single physical slot per entry, and gave Linux the larger default ARC that FreeBSD already used.
Why record size and file size matter
For large files the metadata tends to two copies of a 128-byte pointer per record, plus about a thousandth for the higher levels of indirect blocks: 0.196 percent of the data at 128 KiB and 0.024 percent at 1 MiB. Smaller files cost more because of sector padding. A 1 MiB file at 128 KiB records has eight pointers, 1,024 bytes, padded to a whole 4 KiB sector and stored twice, so 48 TB of such files carries 0.903 percent, 433.59 GB. With 512-byte sectors (ashift 9) the share falls to 0.317 percent, with 8 KiB sectors it rises to 1.685 percent, and at a 1 MiB record size each file fits one block and needs no indirect block at all, leaving 0.122 percent.
The same padding explains a plateau in the record table. For the default 16 MiB files, any record size from 512 KiB to 8 MiB leaves one indirect block of one sector and costs 0.056 percent; only a 16 MiB record removes it, at 0.008 percent. Each doubling of the record size also halves the dedup table, because the pool holds half as many blocks. The RAID & ZFS capacity calculator shows the other side of the trade: larger records waste less space on RAID-Z padding too.
Sizing the SLOG
A SLOG holds sync writes only until the transaction group that contains them reaches the pool. ZFS keeps up to three groups in flight, open, quiescing and syncing, and closes one at least every 5 seconds, so the calculator lets you allow one, two or three groups of writes. Since OpenZFS 2.1.6 the write throttle also slows writers as logged data approaches zfs_wrlog_data_max, twice the dirty data limit of a tenth of RAM capped at 4 GiB, and the zfs(4) manual says that limit should be smaller than the SLOG. From 40 GiB of RAM it is 8 GiB, which is why every link from 5 GbE up needs 8.59 GB on the defaults. The bandwidth calculator converts other link speeds to MB/s.
Published advice disagrees on the rest. Klara suggests 15 seconds of the peak write rate, the FreeBSD Handbook says the log holds roughly one transaction group's worth, TrueNAS recommends a 16 GB device, and Oracle's Solaris guide puts the maximum at half of physical memory. They agree that a SLOG needs little capacity, and that its latency and protection against power loss matter more than its size.
What the figures leave out
The estimate assumes every file is the average size, every block is unique and each dataset keeps the defaults: dnodesize=legacy, copies=1 and redundant_metadata=all. Setting redundant_metadata=most keeps the first level of indirect blocks to one copy, which nearly halves the largest line. It does not count spill blocks for extended attributes or ACLs that overflow a dnode, which take at least a sector for each copy, larger dnodes from dnodesize=auto, each directory's own dnode and blocks, space maps, or old blocks that snapshots keep. Compression of dnodes and directories pulls the other way, so treat the result as an estimate, not a bound.
Small file blocks go to the special vdev only when special_small_blocks is set, and sizing that needs the spread of file sizes, not their average; zdb -b counts the real blocks of an existing pool. With deduplication on, the dedup table also lands on the special vdev unless the pool has a dedup vdev, and zpool status -D reports its size on disk. The data storage converter moves between the GB of disks and the GiB of memory.
Frequently asked questions
How big should a ZFS special vdev be?
Big enough for two copies of the pool's metadata, which depends mostly on the record size and the size of the files. 48 TB of 16 MiB files needs 97.41 GB at the default 128 KiB record size, 0.203 percent of the data, and 27.1 GB at a 1 MiB record size. Every device in the mirror needs that space. If the special vdev fills, new metadata goes to the main pool instead, so running short slows the pool rather than breaking it.
Does a 1 MiB record size reduce metadata?
Yes. Large files tend to two copies of a 128-byte pointer per record, plus about a thousandth more for the indirect blocks above them, which is 0.196 percent of the data at 128 KiB and 0.024 percent at 1 MiB. Files of about 1 MiB gain even more, because at a 1 MiB record size each one fits a single block and needs no indirect block: 48 TB of them carries 433.59 GB of metadata at 128 KiB and 58.59 GB at 1 MiB.
How much RAM does ZFS deduplication need?
About 320 bytes for every block, which is Oracle's figure for one dedup table entry in memory. 48 TB stored in 128 KiB blocks is about 366 million blocks, so the table needs 109.14 GiB, and at a 1 MiB record size it needs 13.64 GiB. The FreeBSD Handbook's rule of 5 to 6 GB of RAM per TB matches an average block of 52 to 62.5 KiB.
How big should a SLOG be?
Big enough for the sync writes ZFS has not yet committed to the pool, which this calculator puts at 5, 10 or 15 seconds of the rate they arrive at. Since OpenZFS 2.1.6, ZFS also slows writers once logged data nears twice its dirty data limit, which is 8 GiB on a machine with 40 GiB of RAM or more. So on the defaults 10 GbE needs 8.59 GB rather than 18.75 GB. Low latency and power-loss protection matter more than capacity.
What happens when a special vdev fills up?
New metadata is written to the normal vdevs instead, so the pool keeps working but loses the speed-up for whatever spills over. Small file blocks stop going to the special vdev sooner, once it is 75 percent full, to keep the rest for metadata. Losing a special vdev loses the whole pool, so its redundancy should match or exceed that of the data vdevs.
How much RAM does the ARC use by default?
From OpenZFS 2.3 the ARC may grow to all of RAM except 1 GiB, or to 5/8 of it if that is more. Linux releases before 2.3 stopped at half of RAM, so on those the ARC figure here may need zfs_arc_max raised. The ARC gives memory back when applications need it, which is why the calculator adds the allowance for the OS and apps on top rather than inside it.
Sources
- zfs(4): tuning of the ZFS kernel module, OpenZFS
- zpoolconcepts(7): overview of ZFS storage pools, OpenZFS
- zfsprops(7): native and user-defined properties of ZFS datasets, OpenZFS
- dmu.c: metadata compression and extra copies, OpenZFS 2.3.0, OpenZFS on GitHub, 2025
- zio.c: compressed sizes rounded to whole sectors, OpenZFS 2.3.0, OpenZFS on GitHub, 2025
- txg.c: three transaction groups in flight, OpenZFS 2.3.0, OpenZFS on GitHub, 2025
- ARC: A Self-Tuning, Low Overhead Replacement Cache, USENIX FAST '03, 2003
- The dedup Property, Oracle Solaris 11.4 documentation
- Oracle Solaris ZFS Version Descriptions, Oracle Solaris 11.2 documentation
- Creating a ZFS Storage Pool With Log Devices, Oracle Solaris 11.3 documentation
- OpenZFS 0.8.0 release notes, OpenZFS on GitHub, 2019
- OpenZFS 2.3.0 release notes, OpenZFS on GitHub, 2025
- Good time to use OpenZFS SLOG and when to avoid it, Klara Systems, 2021
- SLOG Devices, TrueNAS Documentation Hub
- The Z File System (ZFS), FreeBSD Handbook