skip to content

Duplicating a 20 GB file on an APFS volume in macOS finishes almost instantly and the disk's free space barely changes. What did the filesystem actually do, and when is that space eventually consumed?

level: juniorimportance: should knowfreq 58%

answer

  1. no bytes were moved
  2. two file records, one set of extents
  3. copy-on-write pays later, per block
  4. du double-counts what the disk shares
  5. same-volume only

basics

~20 s

APFS made a clone: a second file record pointing at the same on-disk extents rather than a byte-for-byte copy. Space is only consumed later, block by block, as one of the two copies is modified and diverges.

solid answer

~50 s

Nothing was copied. APFS created a **clone** — a new directory entry and file record that reference the *same* extents on disk as the original — so the work is metadata-sized regardless of how big the file is, and almost no new blocks are allocated. Because APFS is copy-on-write, the two files stay independent: when you write to one, only the blocks you actually touch are allocated fresh and rewritten, while everything untouched stays shared. So the 20 GB gets spent gradually, in proportion to how much the two copies diverge, not at duplication time. Two consequences bite people: `du` reports each clone at its full logical size, so the numbers can add up to more than the disk holds; and deleting one clone frees only the blocks no other file still references. Cloning is also confined to a single volume — `clonefile(2)` cannot span volumes, so a cross-volume copy is a real copy.

code

bash · 3 lines
bash
cp -c original.bin clone.bin
du -h original.bin clone.bin
df -h .

go deeper

for a junior

Be able to say the duplicate shares the original's data on disk instead of being written out, and that space is only used as the two copies start to differ.

for a middle

Explain the mechanics: a new inode whose extent records point at existing extents, copy-on-write allocation on first write, and why deleting one copy frees only unreferenced blocks.

for a senior

Show the operational consequence — capacity tooling that sums file sizes overcounts, cloned build artefacts hide real growth, and free space can vanish long after the copies were made.

for a principal

Frame it as a policy question: cheap cloning changes how you design build caches and artefact layouts on macOS, but it decouples reported usage from real usage, so capacity signals must come from the container, not from file sizes.

## What a clone is A clone in APFS is a *second reference to the same data*. The filesystem allocates a new inode and directory entry, points its extent records at the extents the original already occupies, and stops. The cost is a handful of metadata writes — the same whether the file is 20 KB or 20 GB — which is why Finder's **Duplicate** on a huge video file returns before you have let go of the mouse. The underlying primitive is the `clonefile(2)` system call, and macOS `cp` exposes it directly: ```bash cp -c original.bin clone.bin # clone: metadata only cp original.bin copy.bin # ordinary copy: reads and writes every byte ``` ## Why the copies do not corrupt each other Sharing data between two files is only safe because APFS is copy-on-write: a modified block is never overwritten in place. When you write into the middle of `clone.bin`, APFS allocates fresh blocks for exactly the extents you touched, writes the new contents there, and updates *that file's* extent records to point at them. `original.bin` keeps pointing at the old blocks and is completely unaffected. The two files diverge one written extent at a time. That is where the deferred cost lands. Duplicate a 20 GB disk image and change 200 MB of it, and you have spent roughly 200 MB, not 20 GB. Rewrite the whole image and you eventually pay the full 20 GB — just spread over the writes rather than charged up front. ## The two numbers that stop agreeing A clone breaks the everyday assumption that the sizes of the files add up to the space used. **Reported size.** Each clone is a real, independent file with its own full logical size, and it reports the blocks it references. Two 20 GB clones therefore look like 40 GB to `du` or a Finder Get Info, while the container lost only about 20 GB. Any tooling that estimates disk usage by summing file sizes will overcount, which is a routine surprise in backup and capacity scripts on macOS. **Free space on delete.** Deleting one clone removes its file record, but a block is only returned to the container's free pool when nothing references it any more. Delete the duplicate of a file you never edited and you get back almost nothing, because the original still holds every extent. Delete both and the space comes back at once. Users read the first case as "macOS did not actually delete it". ## Where clones come from Clones are not an exotic feature you opt into — they happen constantly: - **Finder Duplicate** and drag-copy within the same volume clone rather than copy. - **`cp -c`** clones explicitly; plain `cp` performs a full copy. - Applications that call `clonefile(2)` directly, including many build and packaging tools that want cheap working copies of large artefacts. What does *not* clone: any copy that crosses a volume boundary. `clonefile(2)` works within one filesystem, so moving data from one APFS volume to another — even two volumes in the same container — reads and writes every byte. The same is true of copies to a network share or a non-APFS disk. ## Clones versus hard links versus snapshots Candidates conflate all three, and an interviewer will probe the difference. A **hard link** is a second directory entry for the *same inode*: one file with two names. Writing through either name changes the single underlying file, and there is no divergence because there is nothing to diverge. A **clone** is two different inodes that merely start out sharing extents; writing through one leaves the other untouched. That independence is the whole point. A **snapshot** is a read-only, point-in-time image of an entire volume rather than of one file. It uses the same copy-on-write sharing, but it pins the state of every file at once and cannot be written to. ## What to say when asked "It cloned the file — a new file record pointing at the same extents, so the operation is metadata-only and effectively free. APFS is copy-on-write, so the copies diverge block by block as either one is written, and that is when the space is actually spent. Watch out for two things: `du` will double-count clones because each reports its full logical size, and deleting one clone frees only the blocks nothing else references."

  • How is a clone different from a hard link, since both give you a second name for the same data?
    A hard link is a second directory entry for one inode — one file, two names, and a write through either name changes the same data. A clone creates a second, genuinely independent inode that merely starts out sharing extents; the first write to either copy allocates fresh blocks and the files diverge. Clones behave like copies, hard links behave like aliases.
  • Why can du report more total usage than the volume physically holds?
    Because `du` sums per-file allocated blocks, and clones share those blocks between files. Two clones of a 20 GB file each honestly report 20 GB, so the sum reaches 40 GB while the container only spent 20. Any capacity estimate built on summing file sizes overcounts on APFS; you have to look at container-level free space instead.

saying these in an interview costs you the question

  • Says APFS copied 20 GB unusually fast because SSDs are fast
  • Thinks editing one clone silently changes the other copy
  • Claims deleting a clone always frees its full reported size
  • Believes clones work across volumes or onto a network share
  • Confuses a clone with a hard link or with a symlink

context