APFS Container and Volume Model
The container
An APFS container is roughly equivalent to a ZFS pool or an LVM volume group (VG). It is the entity that owns the raw disk space. On a standard Mac, your entire SSD is one APFS container (e.g., disk0 is the physical device, disk0s1 is the EFI partition, disk0s2 is the APFS container).
The container manages:
- The block pool (all free and allocated space)
- The space manager (which blocks are free)
- The container-level object map (B-tree mapping object IDs to block addresses)
No volume has exclusive ownership of any portion of the container’s space at rest. All volumes draw from the same pool dynamically. If you have 500 GB free in the container and five volumes, any one volume can expand to consume all 500 GB (unless you’ve set quotas, which almost nobody does).
The volumes
A standard macOS install creates these APFS volumes inside one container:
| Volume name | Role | Typical size |
|---|---|---|
| Macintosh HD | Read-only sealed system OS | 12–16 GB |
| Macintosh HD - Data | All mutable user and system data | Most of your disk |
| Preboot | Boot policies, firmware metadata | ~1 GB |
| Recovery | The recoveryOS environment | ~1 GB |
| VM | Swap files and sleep image | Up to RAM size |
| Update (ephemeral) | Staged OS update, present only during/after an OS download | 10–15 GB |
These volumes are siblings. None of them is “inside” another. They all appear as separate filesystems from the kernel’s perspective, each with its own inode namespace, B-tree, and mount point.
Why this breaks df
When you run df -h /, you’re asking about the volume mounted at /. That volume reports its f_blocks (total) as the container’s total capacity, because from any single volume’s perspective, the entire container pool is potentially available to it. Every volume reports roughly the same “total” capacity.
The “available” field reflects pool-level free space. If another volume (say, VM) grows by 30 GB because you’re running heavy workloads and the OS is swapping, your df -h / available space drops by 30 GB — even though no files changed on your Data volume.
See macOS Disk Reporting for the full breakdown.
How to see the container
diskutil apfs listRead this output from top to bottom:
- The APFS Container section shows you the physical disk, total container size, and container free space. This is the only accurate “how much is really free” number.
- Each APFS Volume entry underneath shows that volume’s name, role, and how much space it has consumed from the pool.
Pay attention to the Capacity Consumed field per volume — this is the actual space that volume has taken from the shared pool.
The sum of all volumes’ Capacity Consumed + Container Free Space should equal Container Total Space.
See also
- APFS - What It Is — overview of APFS design decisions
- APFS - Snapshots — snapshots are per-volume, not per-container
- diskutil - The Ground Truth Tool — how to read
diskutil apfs listoutput