Stop treating your ZFS snapshots like a bottomless trash can
Technical Briefing | 9/27/2026
You set up zfs-auto-snapshot, you forgot about it, and now your pool is gasping for air because it is 98 percent full of snapshots from three years ago. This bit me in prod last quarter when a simple database dump failed because the filesystem hit its reservation limit. We treat snapshots as a safety net, but without a sane retention policy, they become a silent performance killer.
Why older snapshots are lying to you
When you have massive churn on a dataset, the space used by snapshots isn’t just metadata. It is the actual blocks that have changed since the snapshot was taken. If you are running high-transaction workloads, keeping snapshots around for months is essentially duplicating your active data footprint. The df command is notoriously misleading here because it reports total pool space without acknowledging the massive amount of data trapped in hidden, stale snapshots.
zfs list -t snapshot -o name,referenced,used -s used | tail -n 20
- Use zfs list -o space to identify datasets actually hogging the most space via snapshots
- Set a short retention period for frequent hourly snapshots to keep the block chain lean
- Create a script that prunes snapshots based on age rather than just blindly running zfs destroy
The trap of recursive snapshots
Most automated tools default to recursing down your dataset hierarchy. If you have a deep tree of sub-datasets, this creates a sprawl of snapshots that are near-impossible to clean up individually. If you absolutely need recursive snapshots, at least ensure your pruning logic doesn’t orphan child snapshots while holding parent ones. It’s cleaner to snapshot independent volumes at the root and let the data flow dictate your recovery needs.
Before you set your next cron job, check the actual growth rate of your .zfs directory. If you cannot explain what changed in a snapshot from six months ago, you don’t need it. Go delete it before it ruins your next maintenance window.
