Skip to content

Time Machine on APFS: snapshots, network backups, and rollback

How Time Machine uses APFS snapshots for local backups, the per-hour/per-day/per-week retention policy, and what rollback actually does to your filesystem.

Published 5 min read
Time Machine retention policyTime Machine's three-band retention: hourly snapshots for the last 24 hours, daily for the last month, weekly for everything older. Snapshots that fall out of all bands are pruned.SNAPSHOT TIMELINE — NEWEST → OLDESThourly · last 24hdaily · last monthweekly · everything oldernow-24h-30das old as your disk allowsSnapshot lifecycle1. Createfs_snapshot_create — O(1), pins blocks2. Pinsnapshot holds blocks against GC3. Promotemay move between bands as it ages4. Deletefs_snapshot_delete — blocks freedSnapshots are not file copiesEach snapshot is just a retained APFS b-tree XID. Cost at creation: ~milliseconds, regardless of volume size.Cost over time: blocks the snapshot pins that have since been overwritten on the live volume.This is why "TM is full" sometimes means "your hourlies are pinning blocks you've since deleted from the live volume".

Time Machine on a modern Mac is two systems working together: APFS snapshots for the local hourly history, and an external destination (USB drive, NAS, AirPort Time Capsule, or another Mac) for the off-device backup. Both rely on the same APFS snapshot machinery underneath.

This article walks how the pieces fit, what's actually copied when, and what happens when you rollback.

The local snapshots — the always-on safety net

Even without an external destination configured, Time Machine takes local snapshots on your Mac's startup volume:

  • Hourly, when on AC power and idle for a few minutes.
  • Kept for 24 hours, then pruned.

These are pure APFS snapshots — the kernel-level snapshot mechanism. Creation is O(1); they cost essentially nothing in storage at creation, growing only as the live volume diverges from the snapshot.

You can see them with:

tmutil listlocalsnapshots /
# com.apple.TimeMachine.2026-06-01-103214.local
# com.apple.TimeMachine.2026-06-01-093214.local
# ...

And create one manually:

tmutil snapshot

This is the same machinery fs_snapshot_create(2) exposes — see the APFS clones article for the syscall layer.

The destination backups — full + differential

When you configure a Time Machine destination, the backup model gets richer:

  • First backup: full copy of every file from the source to the destination, plus the source's APFS snapshot tree.
  • Subsequent backups: differential — copies blocks that changed since the previous snapshot.

The destination is itself an APFS volume (since macOS 11; older versions used HFS+ with directory hardlinks). The backup process:

  1. Take a fresh APFS snapshot on the source volume.
  2. Compute the diff against the last snapshot the destination knows about.
  3. Stream the changed blocks to the destination's corresponding snapshot tree, allocating fresh blocks on the destination.
  4. Update the destination's snapshot index to record the new backup.
  5. Optionally delete now-redundant snapshots on the source.

Because both sides are APFS with snapshots, the diff is computed at the extent level — the source knows which extents changed since the previous snapshot (the b-tree XID lookup tells it), and it streams just those.

Retention policy

Time Machine's retention has three bands:

AgeKept
Last 24 hourshourly
Last monthdaily
Olderweekly

When a backup completes, Time Machine prunes snapshots that no longer fit any band — e.g., the third hourly from yesterday is dropped because there's already a daily covering that day.

Pruning is just deleting the snapshot, which the kernel handles via fs_snapshot_delete. Blocks that the snapshot was pinning become eligible for garbage collection by the APFS allocator.

Network backups — over SMB to a NAS or Time Capsule

For network destinations:

  1. The destination exposes an SMB share.
  2. Time Machine mounts the share.
  3. Inside the share, Time Machine creates a sparsebundle disk image (a directory of band files that together represent an APFS volume).
  4. Backups go into the sparsebundle — which the local kernel mounts as an APFS volume.

This is why network Time Machine is slower than direct-USB: every block goes through SMB framing + the sparsebundle format + the actual network round-trip. Direct-attached USB or Thunderbolt is dramatically faster.

Rollback — restoring from a snapshot

When you "Enter Time Machine" and restore a previous version of a file:

  1. The Time Machine UI mounts the relevant snapshot read-only at a synthetic path (under /Volumes/.timemachine/).
  2. You browse the snapshot's filesystem as if it were a separate volume.
  3. Selecting a file to restore: the system copies that file from the snapshot mount to the live volume's location.

It's a regular file copy at the user level, exploiting the snapshot's read-only view of the past. The snapshot itself isn't modified; the live volume gains a fresh copy.

For a system-wide rollback (restore everything to a previous snapshot), the mechanism is different:

  1. Boot into recoveryOS.
  2. recoveryOS knows how to do a fs_snapshot_revert on the boot volume.
  3. The live volume's root b-tree gets replaced with the snapshot's root.
  4. All changes since the snapshot are lost (the blocks become garbage-collectable).

System-wide revert is exposed via tmutil restore and friends. It's much faster than a file-by-file restore — O(1) at the b-tree level.

What happens during a backup, on the kernel side

The user-space backup daemon (backupd) drives the show. Kernel side:

  1. fs_snapshot_createbackupd creates a fresh snapshot. Kernel allocates a new snapshot tree, marks all current blocks as pinned. ~milliseconds, regardless of volume size.
  2. fs_snapshot_diff (private SPI) — backupd asks the kernel which extents changed since the previous snapshot. The kernel walks the b-tree comparing XIDs.
  3. File reads from the snapshotbackupd reads from the snapshot mount; the kernel reads the right block versions via the snapshot's b-tree.
  4. Block-level streaming to destinationbackupd writes to the destination, which goes through its own APFS volume's normal write path.
  5. fs_snapshot_delete — old snapshots no longer needed get deleted; the kernel marks their pinned blocks as eligible for reclamation.
apple-oss-distributions/xnubsd/sys/snapshot.hfs_snapshot_* syscalls — what Time Machine uses on the source side.View on GitHub(line )

What surprises newcomers

  • Time Machine works even without a destination. Local hourly snapshots are always on for the boot volume.
  • A 1-hour backup of 1 TB takes seconds. Snapshot creation is O(1); the differential is small.
  • A snapshot doesn't "save space" — it pins blocks. Snapshots full of unique data consume the data's space. Snapshots of mostly-unchanged data consume almost nothing.
  • Network Time Machine performance is constrained by the sparsebundle, not just the network. The disk-image-in-a-share architecture is the bottleneck.

For the snapshot syscalls and the APFS COW machinery this builds on:

apple-oss-distributions/xnubsd/vfs/vfs_syscalls.cWhere the snapshot syscalls land in the BSD layer before dispatching into APFS.View on GitHub(line )

And the APFS clones and snapshots article — the syscall-level layer Time Machine builds on top of.

Related

How macOS encrypts every byte on disk — per-file keys derived in the SEP, the volume encryption key wrapped by user password, hardware AES in the SSD controller.
Every block on an APFS volume is reachable through one b-tree — the object map. Here's how it's laid out, how it survives a write, and why APFS is self-checksumming by design.
clonefile, fclonefileat, fs_snapshot — three syscalls that let you copy 50 GB in 50 milliseconds. Here's what happens under each one, and what doesn't get copied.