Stop lying to yourself about your ZFS snapshot retention
By Saket Jain Published Linux/Unix
Stop lying to yourself about your ZFS snapshot retention
Technical Briefing | 9/6/2026
We have all seen it happen. You set up a fancy automated script to rotate your ZFS snapshots, verify it once, and then ignore it for six months. Then you wake up at 3 AM because your storage pool is read-only, and you realize that your snapshots didn’t actually prune because the hold flag was still set from that manual recovery you did last summer. It’s a classic case of hidden state sabotaging your operational reliability.
Why your pruning scripts are failing silently
Most automated tools rely on naming patterns to find what to delete. But if you have ever issued a zfs hold to keep a backup while debugging a filesystem corruption, that snapshot stays pinned forever. Your cron job tries to delete it, the API returns an error, and the script just moves on to the next one, leaving the dead snapshot consuming space. If you don’t check for holds explicitly, you are just waiting for a disk full emergency.
zfs list -t snapshot -o name,holds | grep -v 'none' | awk '{print $1}'
- Audit snapshots with active holds using the zfs holds command regularly.
- Check your pool space fragmentation which snapshots exacerbate if they grow large.
- Include a safety check in your deletion scripts to verify return codes of the zfs destroy call.
Don’t just trust that the automation finished because the exit code was zero. Most scripts don’t handle partial failure well. I have seen them skip ten deletions because of one stale hold, leaving the rest of the pool to bloat. If you really want to sleep through the night, add a monitoring check that alerts you if the number of snapshots exceeds a sane threshold for any given dataset.
