Stop ZFS from wrecking your latency during heavy scrubs
Technical Briefing | 7/19/2026
I remember the first time I ran a full pool scrub on a production database server. Everything was fine for the first hour, and then the application latency spiked so hard the monitoring dashboard turned solid red. It turns out ZFS scrubbing is a resource hog by design, and if you haven’t tuned it, it will happily steal every IOPS cycle from your live workloads.
Why the default behavior bites you in the ass
The kernel tries to balance the scrub priority, but on modern NVMe arrays, it moves fast enough to completely saturate the I/O bus. Most admins just let it rip during business hours because the docs say it has a low priority. Don’t believe it. If your disk queue depth hits the roof, your application performance is effectively dead until the scrub pauses.
echo 3 > /sys/module/zfs/parameters/zfs_scrub_delay
- Increase zfs_scrub_delay to inject a millisecond gap between I/O ops
- Cap the zfs_scrub_min_time_ms to ensure background tasks don’t monopolize the bus
- Set zfs_scan_idle to 1 so the pool waits for actual idle time before kicking off
Regaining control over the I/O queue
Tweaking these module parameters is the only way to keep the scrub running without impacting production latency. I’ve found that setting the delay to 3 or 4ms on SSD-backed pools is the sweet spot. It extends the total scrub time, but it stops the user-facing app from timing out. Next time a scrub fires up, keep an eye on your disk latency charts rather than just waiting for the progress bar to finish.
