Snapshots: full, incremental, copy-on-write
Why is a snapshot a garbage-collection policy rather than a copy, and what does keeping one cost?
Four terms that are often mixed up are really one mechanism with different lifetimes:
- A checkpoint is a consistent image whose only consumer is recovery and whose life is one interval.
- A snapshot is the same image promoted to a named, externally addressable object with a retention policy.
- A backup is a snapshot moved to an independent failure domain.
- PITR (point-in-time recovery) is a backup plus the retained log from then until now.
Flink proves this framing: a checkpoint is owned by the system and deleted automatically; a savepoint is the identical artifact, triggered by a user, named and kept. Same bytes, different lifetime. In general, the difference is system-owned and auto-deleted versus user-owned and retained.
Three ways to build a snapshot (derived from cost)
Full copy. Cost is O(dataset) in time and space. And while you copy, the source keeps changing, so you need either a pause or a consistent read view. N snapshots cost N × dataset.
Copy-on-write (CoW). Do not copy anything. Freeze the root of the mapping structure and stop the collector from reclaiming anything that is reachable from it. Creating the snapshot is O(1): it is a metadata operation. Space is O(data changed since). This is only possible on storage that already has an indirection layer, which every medium that cannot update in place grows. The indirection layer you were forced to build for one reason makes snapshots almost free.
This gives the most useful sentence of this section: a snapshot is not a copying operation; it is a garbage-collection policy. "Snapshot" means "these blocks are not reclaimable". ZFS, Btrfs, Iceberg (a table format for data lakes), EBS (Amazon's block volumes), LVM thin pools and Git all implement it the same way, because they all already had a reference-counted indirection layer.
Incremental / differential. Copy only what changed since a reference point. This needs change tracking: a dirty bitmap, a block-change log, or the CoW metadata itself. Restore cost = the base + the whole chain of increments. So restore time grows with chain length, and the cure is periodic re-basing (a synthetic full: build a new full image from the old base plus increments).
This is the same equation as the checkpoint interval with the roles swapped: chain length trades capture cost against reconstruction cost. LSM levels (the layered files of write-optimized stores), columnar delta files, Iceberg snapshot chains, git packfiles, video keyframes and backup chains all have this one shape. As a rule: every incremental scheme has a chain length that trades capture cost against reconstruction cost; periodic re-basing is the only cure, and its interval is the real knob.
What a CoW snapshot is not
It shares blocks with the live data and lives in the same failure domain. It protects against logical errors (a bad UPDATE, a bad deploy) and against nothing else: not media failure, not controller firmware bugs, not rm -rf of the whole pool, not a stolen credential.
And it has a continuous cost. Once a snapshot exists, every overwrite in the live data must allocate a new block instead of overwriting. So the live workload pays continuously for the snapshot's existence, in write amplification and pool space, for as long as the snapshot is kept. A forgotten snapshot on a CoW pool is a slow-motion outage. This is the same shape as undo pinned by the oldest read view (Logs and undo).
The multi-volume trap
This one kills real production systems. A block-level snapshot is crash-consistent, not application-consistent. It captures the state that a power loss would have produced. That is fine, because the database's own recovery knows how to handle that state, but only if the snapshot is atomic across every device that the write-ahead rule spans.
If you snapshot the data volume and the log volume separately, you can capture a state in which a page's change is present but its log record is not. That image breaks the WAL rule and cannot be recovered. It looks fine until the day you restore it. Hence pg_backup_start, Windows VSS writers and consistency groups (snapshots of several volumes taken at one instant).