| your Linux construction kit
Source
← Back to ZFS Overview

Tuning for Workloads — defaults are for nobody.

Default ZFS settings are not optimized for any specific workload. Databases have completely different needs than media storage. Compression, ARC settings, record sizes, and logbias all dramatically affect performance. Here's how to tune for each.

Databases (PostgreSQL, MySQL)

The database recipe

zfs create -o recordsize=16K \
           -o logbias=throughput \
           -o primarycache=metadata \
           -o compression=lz4 \
           -o atime=off \
           rpool/srv/postgres

Why 16K? PostgreSQL operates in 8K blocks. Using the default 128K recordsize causes massive read/write amplification — ZFS reads 128K to service an 8K request. 16K gives the best balance (8K works too but 16K handles mixed workloads better).

SLOG recommended. Databases use sync writes heavily. Without an SLOG, every commit waits for the write to hit spinning rust. An enterprise NVMe SLOG with power loss protection drops commit latency from milliseconds to microseconds.

For ZVOLs (raw block access): use volblocksize=8K for databases, 16K for general VMs.

VM storage

The VM recipe

# Use ZVOLs, not datasets, for VM disks
zfs create -V 40G -s \
           -o volblocksize=16K \
           -o compression=lz4 \
           rpool/srv/vms/my-vm

# NEVER use RAIDZ for VM storage. Use mirrors.

Why ZVOLs? VMs need raw block access. Datasets add a POSIX layer that VMs don't need and that adds overhead. ZVOLs give the guest OS direct block access through ZFS.

Why not RAIDZ? VMs generate random I/O patterns. RAIDZ's read-modify-write penalty destroys VM performance. Mirrors handle random I/O linearly.

Media & large files

The media recipe

zfs create -o recordsize=1M \
           -o compression=zstd \
           -o atime=off \
           rpool/srv/media

Why 1M recordsize? Large sequential files (video, images, backups) benefit from large records. ZFS reads and writes in bigger chunks, reducing metadata overhead and improving throughput. For small files, 128K (default) is fine. For media, 1M is optimal.

Note on compression: Already-compressed media (MP4, FLAC, JPEG) won't compress further. But metadata, subtitles, NFO files, and text will compress 3-5x. ZSTD gives better ratios than LZ4 with slightly more CPU. For media servers, the tradeoff is worth it.

General file storage

The general recipe

zfs create -o compression=lz4 \
           -o atime=off \
           rpool/srv/data

LZ4 compression is nearly free in terms of CPU and typically gives 1.5-2x space savings. There is almost no reason to leave compression off. Disabling atime prevents unnecessary disk writes every time a file is read.

Quick reference

WorkloadStorage TyperecordsizeCompressionSLOG?VDEV Type
PostgreSQLDataset or ZVOL8K-16Klz4YesMirrors
MySQLDataset or ZVOL16Klz4YesMirrors
VM disksZVOLvolblocksize=16Klz4RecommendedMirrors
NFS sharesDataset128Klz4YesMirrors or RAIDZ2
Media filesDataset1MzstdNoRAIDZ2
Backups/archivesDataset1Mzstd or gzipNoRAIDZ2/3
ContainersDataset128Klz4NoMirrors + Special
General filesDataset128Klz4NoAny