Improve the way you make use of ZFS in your company.
Did you know you can rely on Klara engineers for anything from a ZFS performance audit to developing new ZFS features to ultimately deploying an entire storage system on ZFS?
ZFS Support ZFS DevelopmentAdditional Articles
Here are more interesting articles on ZFS that you may find useful:
- When RAID Isn’t Enough: ZFS Redundancy Done Right
- ZFS Enabled Disaster Recovery for Virtualization
- Klara at the OpenZFS User & Developer Summit 2025
- How to Set Up a Highly Available ZFS Pool Using Mirroring and iSCSI
- Understanding Storage Performance Metrics
ZFS is more than just a filesystem, it is a modern software-defined storage management system that combines exceptional data integrity, flexibility, and ease of management into a single package. While many users are familiar with the basics of ZFS, such as creating pools and datasets, the real power lies in leveraging its advanced data management features.
Any advanced data management scheme starts with the fundamental building blocks: snapshots, clones, and bookmarks. These mechanisms provide lightweight, instantaneous point-in-time views of your data and allow it to be replicated across systems and locations, or even branched to provide new environments or testbeds without duplicating data or risking its integrity.
This week, we’ll dive deep into these three core concepts of advanced ZFS dataset management and explore how they work, some practical applications, and any trade-offs you need to keep in mind.
Snapshots: Immutable Point in Time
The copy-on-write nature of ZFS provides its greatest strength: durability in the face of unexpected shutdowns or crashes. Whenever data is modified, the new data is written to a freshly allocated block on disk, rather than overwriting the original version. This ensures that if the write is interrupted, the complete original copy is still available.
This design also enables inexpensive, instantaneous snapshots. Since any new data is written to a different location, all a snapshot needs to do is prevent the original version of the data from being reclaimed by the filesystem until the last snapshot is removed. Compared to the snapshot features in other filesystems or those found in many hypervisors, this approach means ZFS is not required to perform extra work for writes that occur while one or more snapshots exist.
Snapshots enable you to capture the exact state of a file system at a specific moment in time, unlocking significantly improved backup options. With traditional backup systems, files are copied at different times throughout the course of the backup job. This means that the files copied late in the job will be from a different time than the files copied at the start of the job. By using ZFS snapshots as the source for backups, you ensure that the entire backup, even if it takes many hours to run, has copies of every single file from the same instant.
Snapshots are entirely immutable; they cannot be changed at all. If you would like to change a snapshot, you must first create a clone of the filesystem based on that snapshot, which will be covered in more detail in a later section.
How Snapshots Work
Many people expect that when you create a snapshot, ZFS will mark all of the blocks currently used by the dataset as being in use by the snapshot, or that every time a block is overwritten, the filesystem must check if the block is part of the snapshot and take extra steps to keep the original copy of the data as well. These approaches are, in fact, how most other filesystem snapshot mechanisms work after all.
However, ZFS works a bit differently. ZFS has a larger per-block metadata object, called a block pointer. Along with the details of where the data is stored on disk, how large it is, how it is compressed, if it is encrypted, and the checksum, ZFS also stores the “birth time” of the block, as the transaction number when the block was created.
When it’s time to delete data, ZFS just compares the birth time of the block to the birth time of the next oldest snapshot. If the block is newer than the next oldest snapshot, it is not included in the snapshot and can be freed immediately.

To further optimize this, ZFS keeps “dead lists”. When a file is deleted, and its data is retained because it is referenced by a snapshot (in other words, the block’s birth time is older than the snapshot, so it was not freed as above), it is added to the list of “dead blocks” attached to that snapshot. Later, when it’s time to prune that snapshot, rather than having to scan the entire pool for blocks that need freeing, ZFS has a list it can quickly iterate over.
The same process happens recursively, as ZFS walks this “dead list” while destroying a snapshot. If a block’s birth time is older than the NEXT oldest snapshot, it is moved to that snapshot’s dead list, rather than being freed, because it is still referenced by that snapshot.
With this simple mechanism, ZFS can efficiently track which blocks need to be kept, and which can be safely freed for reuse, all without having to keep a massive map of which blocks belong to which snapshots. This is how ZFS is able to support a nearly limitless number of snapshots, and why the read and write performance of the pool is never impacted by the number of snapshots present.
Creating and Managing Snapshots
Creating a snapshot
A snapshot is created with just a single command, referencing the dataset you want to snapshot, and defining a name for the snapshot itself:
zfs snapshot pool/dataset@label
The @label portion identifies the snapshot. This is where a naming convention can be helpful. It is best practice to identify the date/time of the snapshot, and for manually created snapshots, the reason for the snapshot, or an indication of what data it is preserving. For example: @2025-09-15_15:35_before_database_upgrade.
It is also possible to create a recursive snapshot. This will create a snapshot with the same name for an entire hierarchy of datasets (a dataset and all of its children).
For example, you can snapshot all of the datasets in a pool, creating a consistent snapshot with the same name, capturing the contents of every dataset at the same instant:
zfs snapshot -r pool@2025-09-16_11:15_before_the_big_change
Lastly, you can also snapshot multiple datasets at once, to ensure consistency:
zfs snapshot pool/database@my-database-snapshot pool/var/www@my-webapp-snapshot
Listing Snapshots
ZFS has a very expressive command-line interface. To start with the basics:
zfs list -t snapshot
This lists all of the snapshots in the pool. You can constrain this to a specific subset of datasets, using -r (recursive) or -d N (depth limited):
zfs list -t snapshot -r pool/home/allan
This lists all snapshots of my home directory, and any child datasets within it.
zfs list -t snapshot -d 2 pool/home
With the -d flag, ZFS will list snapshots recursively, but limit the depth of the search to 2 levels below the target, so it will find snapshots of all users’ home directories and pool/home/allan/backups, but will omit deeper snapshots such as pool/home/allan/research/nvme.
Accessing Snapshots
There are two ways to access the contents of a snapshot: using the “snapdir” (a hidden synthetic directory: .zfs/snapshot/), or by mounting the snapshot:
ls -al /pool/snapshot/.zfs/snapshot/label/or
mount -t zfs poolname/dataset@label /mnt/destination
ls -al /mnt/destination
In both cases, you can then copy individual files out of the snapshot to restore them, and just to see what a file looked like in the past.
Reverting to a Snapshot
In order to restore a dataset to the state it was in at the point of the snapshot, you can “roll back” to the snapshot:
zfs rollback pool/dataset@label
This instantly reverts the dataset to its previous state. Note, however, that rolling back destroys any changes made after the snapshot (more on ways around this in the next section), and therefore, in order to roll back to an older snapshot, you will need to destroy any newer snapshots first.
Clones: Writable Snapshots
Snapshots are extremely powerful, but are somewhat limited in certain situations because they can never be modified. What if I want to snapshot my production database and use a copy of it in a development lab, but the development version of the application needs to be able to make changes? That is where the ZFS clone feature comes in.
A clone is a writable version of a snapshot, basically a fork of a filesystem at the point in time of the snapshot. All unmodified data blocks are shared between the clone and the snapshot (and therefore, the original dataset as well). Creating a clone of a snapshot consumes only a few kilobytes of space for metadata. Then, as you modify files or create new ones, additional space is consumed, but the shared blocks—which are often the majority of data in these use cases—do not consume any additional space.
Creating a Clone
Creating a clone is as simple as creating a dataset or a snapshot, since it simply involves creating a new dataset that shares the contents of a snapshot:
zfs clone pool/mydata@label pool/newclone
This will create a new cloned dataset, “newclone”, which is a copy of pool/mydata from the instant of the snapshot “label”. This creates a parent-child relationship between the “label” snapshot and the clone. The “origin” property of a clone will point to the snapshot that the clone is based on. While the clone exists, that snapshot, and the dataset it is a snapshot of, cannot be destroyed.
Promoting a clone
This parent-child relationship can be inverted to work around this limitation. If you have a dataset and a snapshot, and create a clone from them, but later decide that you only wish to keep the clone, and destroy the original dataset, it is simply a matter of changing “ownership” of the snapshot from the original dataset (the origin) to the clone.
zfs promote pool/newclone
After this operation, the original dataset (pool/mydata) will now be a clone of pool/newclone@label. Once this change is made, you are free to destroy the original dataset, since the snapshot now belongs to newclone.
Some of the most powerful use cases enabled by clones:
Development and Testing
Developers can branch off production data into an isolated clone, test upgrades or changes, and throw them away afterwards—all without touching the original dataset.
This mechanism has been used by a number of customers to prepare for database engine or scheme updates and ensure smooth operations of all applications.
Rapid Provisioning
Virtual machines and containers can be spun up quickly as clones of a base golden image. This not only avoids copying gigabytes of data for each new VM or container, but also enables block-sharing between the containers, further reducing storage requirements.
Experimentation Without Risk
Need to try a destructive process? Clone a snapshot and test away, knowing the original is safe. Clones of the root filesystem with minor (or major) changes are the cornerstone of ZFS Boot Environments.
Bookmarks: Lightweight Change Markers
Snapshots are powerful, especially when combined with ZFS’s replication features. What if I told you that in order to perform incremental replication, you only need to keep the metadata of a snapshot, without keeping its associated data? That’s where bookmarks come in. A bookmark is essentially the bare minimum metadata (the GUID of the snapshot, and the transaction group it was created in), without holding onto any data blocks.
Replication uses the same mechanism that snapshots rely on: the birth time of blocks. By comparing birth times, ZFS can identify which blocks changed between two snapshots, enabling only those changes to be replicated. With that in mind, it turns out you only need the birth time from the “starting” snapshot, not the original copies of the data that have since been overwritten, because those will already exist on the destination of the replication.
Creating a Bookmark
A bookmark is created from a snapshot, and then allows that snapshot to be destroyed, reclaiming the space consumed by blocks unique to it, while retaining the metadata needed for incremental replication (send everything that changed since this bookmark, up to this future snapshot):
zfs bookmark pool/mydata@snap pool/mydata#bookmark
The hashtag or octothorp symbol (#) in the name of a bookmark distinguishes it from a snapshot, which uses the at-symbol (@).
Replication Retention
One of the most useful features of ZFS replication is the ability to keep data longer on the backup server than on the primary, extending the retention period while still enabling continued incremental replication.
If you replicate a snapshot to a remote site, you can create a bookmark from that snapshot on the sending side, then delete the snapshot itself. This reclaims the space used by any data that had been overwritten since that snapshot, while still being able to incrementally replication any changes that happen after the bookmark.
Remember, it is still required that the source and destination pools have a common reference point, a specific snapshot. On the source, however, that snapshot can be replaced with a bookmark.
Conclusion
ZFS is unique in how seamlessly it integrates snapshots, clones, and bookmarks to provide extremely powerful storage management that remains simple and easy to operate. Snapshots provide instant recovery points and protection from ransomware, clones enable flexible branching of data, and bookmarks allow efficient replication without local snapshot sprawl. Used together, these tools form the backbone of advanced dataset management.
By mastering these features, administrators gain not only resilience against mistakes and disasters but also the agility to move faster—deploying test environments, replicating data across geographic regions, and experimenting safely. The real beauty is that all of this comes built into ZFS, available with just a few commands and a thoughtful management strategy.
If you would like to explore how you can take better advantage of snapshots, clones, and bookmarks to improve data security, expand flexibility, or extend your backup retention period, Klara’s ZFS Support Subscription can help you implement best practices, monitor and keep your storage environment healthy.

Allan Jude
Principal Solutions Architect and co-Founder of Klara Inc., Allan has been a part of the FreeBSD community since 1999 (that’s more than 25 years ago!), and an active participant in the ZFS community since 2013. In his free time, he enjoys baking, and obviously a good episode of Star Trek: DS9.
Learn About Klara




