I started with a practical question: was this Mac's storage behaving badly, or was normal Apple SSD behaviour being mistaken for an APFS or swap problem?
The health checks were almost disappointingly clean. SMART was verified, TRIM was enabled, there were no thermal warnings, and the Data volume still had about 266 GiB free. The interesting answer appeared only after a queue-depth-one, uncached 100 GiB write made the NAND move from its fast path to its sustained path.
| 92 GiB | high-speed write window in this free-space state |
|---|---|
| 2.3–2.5 GiB/s | typical rate before the transition |
| 429 MiB/s | median across GiB 94–100 |
| 58% free | APFS Data volume headroom during the test |
The drive held roughly 2.3–2.5 GiB/s through GiB 92, fell during GiB 93, and then settled around a 429 MiB/s median. After the file was deleted and the blocks became reusable, a new 4 GiB write immediately returned to full speed.
The defensible conclusion is not that every APPLE SSD AP0512Z contains a fixed 92 GiB cache. It is that this drive, at this level of free space, exposed a dynamic pseudo-SLC window of about 92 GiB. Apple's firmware policy remains undocumented.
The result also answers the original tuning question. There is no hidden APFS switch worth chasing here. Free space, competing I/O and application write patterns matter; speculative filesystem surgery does not.
Start with the boring answer: the drive is healthy
| Property | Observed value |
|---|---|
| SSD model | APPLE SSD AP0512Z |
| Controller | AppleANS3CGv2Controller |
| Controller firmware | 2973.120 |
| Interface | Apple Fabric, internal |
| Controller-reported capacity | 512,000,000,000 bytes |
| macOS-visible namespace | 500,277,792,768 bytes |
| Main APFS container | Approximately 494.4 GB |
| Data volume | Approximately 460 GiB |
| Data volume available | Approximately 266 GiB |
| Data volume use | Approximately 40% used, 58% free |
| Logical/physical block size | 4 KiB |
| TRIM | Enabled |
| SMART | Verified |
| FileVault | Enabled |
| Time Machine during testing | Idle |
| Data-volume snapshots | None |
| Thermal/performance warnings | None recorded |
The physical I/O device is disk0. APFS synthesized/container identifiers include disk3, so targeted iostat monitoring should use the physical device or the general iostat -d view rather than assuming disk3 is the hardware device.
The controller exposes more than I expected
IORegistry exposed the following controller characteristics:
| Controller property | Value |
|---|---|
| NAND vendor | SanDisk |
| NAND identifier | tlc_3d_g5_2p_512 |
| Default bits per cell | 3 |
| Cell type | 3, TLC |
| NAND page size | 16 KiB |
| Native/TLC pages per block | 1,344 |
| SLC pages per block | 448 |
| Native/TLC sectors per full band | 86,016 |
| SLC sectors per full band | 28,672 |
| NAND buses | 4 |
| Dies per bus | 2, 2, 2, 2 |
| Total dies | 8 |
| Controller preferred I/O size | 1 MiB |
| Controller command-pool size | 64 |
| Encryption type | AES-XTS |
The SLC geometry is exactly one-third of the native TLC geometry:
448 / 1,344 = 1/3pages per block.28,672 / 86,016 = 1/3sectors per full band.- At 16 KiB per page, a block represents approximately 7 MiB in SLC mode and 21 MiB in native TLC mode.
This is the expected capacity tradeoff when TLC NAND temporarily stores one bit per cell instead of three. Pseudo-SLC is not a separate cache chip; it is the same TLC NAND operated in a faster, lower-density mode.
Making the cache show itself
The goal
Determine whether the SSD exhibits a capacity-dependent high-speed write region followed by a persistent lower plateau, while avoiding macOS page-cache distortion.
Method
- Created a disposable test directory on the internal Data volume.
- Marked the directory as excluded from Time Machine and Spotlight indexing.
- Used 1 MiB write requests, matching the controller's preferred I/O size.
- Enabled macOS
F_NOCACHEon the file descriptor. - Issued
F_FULLFSYNCafter every 1 GiB. - Wrote a 100 GiB test file and reported throughput for each GiB.
- Used random source data; FileVault's sector encryption also prevents a repetitive on-NAND zero pattern.
- Deleted the file immediately after the test.
- Performed a separate 4 GiB recovery test after cleanup.
- Verified physical-device write counters, free space, snapshots, and thermal state afterward.
This was a queue-depth-one, strongly synchronized test. Its post-cache speed should not be treated as the maximum throughput achievable by every application, but it is well suited to identifying a write-cache transition.
The cliff
| Test region | Result |
|---|---|
| GiB 1–15 | Variable warm-up/background range, approximately 1.6–2.8 GiB/s |
| GiB 16–92 | Mostly 2.3–2.5 GiB/s |
| GiB 93 | 770.2 MiB/s; transition occurred within this segment |
| GiB 94–100 | 264.3–569.9 MiB/s |
| GiB 94–100 median | 428.9 MiB/s |
| Approximate slowdown | 5.7× versus a representative 2,445 MiB/s pre-cliff rate |
| Total 100 GiB elapsed time | 60.6 seconds |
Detailed transition and post-cache measurements:
| Segment | MiB/s |
|---|---|
| 93 GiB | 770.2 |
| 94 GiB | 264.3 |
| 95 GiB | 569.9 |
| 96 GiB | 318.0 |
| 97 GiB | 428.9 |
| 98 GiB | 349.0 |
| 99 GiB | 432.1 |
| 100 GiB | 446.3 |
The fast path comes back
After the test file was deleted and its blocks became reusable, a new uncached 4 GiB write produced:
| Recovery segment | MiB/s |
|---|---|
| 1 GiB | 2,282.5 |
| 2 GiB | 2,450.4 |
| 3 GiB | 2,686.8 |
| 4 GiB | 2,814.9 |
The return to full speed argues strongly against the earlier cliff being a lasting thermal limit. macOS also recorded no thermal or performance warning.
Proving the bytes reached disk0
Before the 100 GiB test, the physical-device write counter was:
23,067,131,904 bytes
Afterward it was:
130,736,635,904 bytes
The counter increased by 107,669,504,000 bytes. A 100 GiB write contains 107,374,182,400 bytes, leaving only about 295 MB attributable to concurrent system activity. This confirms that the benchmark reached the physical SSD rather than measuring a RAM-backed file cache.
The test and recovery check wrote 104 GiB in total. This is minor as a one-time diagnostic, but the benchmark should not be repeated routinely because synthetic writes consume NAND endurance.
What the cliff means
The evidence chain is:
- The drive identifies as native three-bit TLC.
- Apple exposes explicit one-bit SLC block and band geometry.
- SLC capacity is exactly one-third of TLC capacity.
- The drive maintained a high write plateau through 92 GiB.
- It entered a substantially lower, persistent plateau beginning during GiB 93.
- High initial speed returned after deletion/TRIM made blocks reusable.
- No thermal warning accompanied the transition.
The practical write path is therefore:
Host write
|
v
Available TLC blocks operated in one-bit pseudo-SLC mode
| approximately 2.4 GiB/s in this test
|
+--> background folding into native three-bit TLC
|
v
Cache/folding headroom exhausted
|
v
Direct TLC writes + folding + garbage collection
| approximately 429 MiB/s median in this test
v
Persistent native storage
Why 92 GiB fits the free-space geometry
At test time:
- APFS reported approximately 266.389 GiB available.
- The controller reported 512,000,000,000 bytes, while the exposed namespace was 500,277,792,768 bytes.
- That namespace gap is 11,722,207,232 bytes, or approximately 10.917 GiB.
A simple one-bit-capacity model gives:
(266.389 GiB + 10.917 GiB) / 3 = 92.435 GiB
The measured high-speed extent was 92 GiB. The close alignment is strong evidence of a free-space-sensitive cache policy, but it is not an official allocation map. Apple does not expose whether every hidden block is eligible for pseudo-SLC or how firmware divides space among caching, garbage collection, metadata, and endurance reserves.
Proving the exact dynamic-size formula would require repeating destructive write tests at multiple disk-fill levels. The additional wear and temporary space consumption are not justified by the practical value of that result.
There is no magic APFS switch
APFS and the Apple storage controller are self-tuning. There is no supported global APFS performance setting for:
- Pseudo-SLC cache size.
- Flash garbage collection.
- Queue depth.
- Filesystem block size on the existing system volume.
- Disabling copy-on-write or journaling.
- Manual internal-SSD TRIM scheduling.
Changes that can help
- Keep substantial free space. At least 20–25% is a reasonable minimum; 30% or more is preferable for sustained-write workloads. The current 58% free is excellent.
- Exclude only disposable, high-churn data from indexing and backup. Examples include reproducible build output, dependency caches, VM scratch data, and disposable download/extraction directories.
- Keep high-churn scratch data outside iCloud Drive. This prevents cloud synchronization from competing with the workload.
- Improve application I/O patterns. Larger sequential writes, sensible batching, fewer unnecessary synchronous flushes, and workload-specific database settings can matter much more than filesystem changes.
- Avoid simultaneous heavy writers. Time Machine, Spotlight, cloud sync, extraction, VM images, and large downloads can compete for SSD bandwidth.
- Use a fast Thunderbolt NVMe SSD for scratch workloads that repeatedly exceed the internal drive's sustained post-cache behavior.
Changes I would not make
- Do not disable FileVault; Apple Silicon provides hardware AES-XTS acceleration.
- Do not disable journaling or attempt to disable APFS copy-on-write.
- Do not run
trimforce; TRIM is already enabled. - Do not defragment the SSD.
- Do not use
sudo purgeor cache-cleaning tools as a performance treatment. - Do not routinely delete normal APFS snapshots.
- Do not resize the APFS container merely to leave unpartitioned “over-provisioning.” Free, TRIMmed APFS blocks already provide controller headroom.
- Do not create a separate APFS volume expecting higher physical throughput; volumes in one container share the same SSD and free-space pool.
- Do not move or manually tune macOS swap.
Where free space still matters for swap
macOS stores dynamically allocated swap files under /private/var/vm on the APFS Data volume. The approximate pressure path is:
Unified-memory pressure
-> cache reclamation
-> memory compression
-> dynamic swap files on APFS
-> SSD pseudo-SLC/TLC and garbage collection
Free space affects swap in several ways:
Swap capacity
macOS creates and expands swap files as needed. If APFS cannot allocate additional blocks, macOS may spend time purging caches and reclaiming space, show an application-memory warning, or terminate processes when memory cannot be reclaimed.
Write latency and garbage collection
Swap produces small, latency-sensitive writes. With ample free blocks, the controller can allocate new pages and erase old blocks efficiently. Near full capacity it must relocate more live data, increasing write amplification and latency variability.
Pseudo-SLC headroom
More free NAND generally allows a larger pool of blocks to operate temporarily in SLC mode. The measured 92 GiB sequential allowance is not a literal swap-cache quota, because swap is more random and bursty, but the same free-block principle applies.
Swap-in contention
Free space primarily helps allocation and swap-out writes. Existing swap pages can be read without allocating space, but swap-in latency still suffers when the controller is busy with folding, garbage collection, backup, indexing, or other application I/O.
Conservative free-space rules of thumb:
| Available space | Expected behavior |
|---|---|
| 25% or more | Comfortable APFS and controller headroom |
| 15–25% | Usually fine; sustained writes may lose fast cache sooner |
| 5–15% | More garbage collection and higher latency risk |
| Below 5% | Serious risk of stalls, failed allocations, and application-memory warnings |
For this 512 GB drive, maintaining at least approximately 100–125 GB available is a reasonable target for workloads that regularly experience memory pressure. The observed 266 GiB available is well above that target.
Even under ideal storage conditions, swap remains dramatically slower than unified memory. Abundant free space keeps swap from becoming unnecessarily worse; it cannot make swap comparable to RAM.
What I would actually do
- Leave APFS, FileVault, TRIM, snapshots, and virtual-memory settings unchanged.
- Continue keeping substantial free space; the present 266 GiB is excellent.
- Use Spotlight and Time Machine exclusions only for genuinely disposable, high-churn directories.
- If an application is slow, profile its I/O and memory behavior rather than applying filesystem “tweaks.”
- Treat sustained writes above approximately 92 GiB as a special workload that may encounter the measured cache cliff under similar free-space conditions.
- Do not repeat the synthetic 100 GiB test unless a firmware update or material change in drive fullness creates a specific reason to revalidate it.
Reproducing the inspection
# Hardware and storage metadata
system_profiler SPHardwareDataType SPNVMeDataType
ioreg -r -c AppleANS3CGv2Controller -l
diskutil list
diskutil apfs list
diskutil info /
# Capacity and snapshots
df -h /System/Volumes/Data
diskutil apfs listSnapshots /System/Volumes/Data
tmutil listlocalsnapshots /
# Live physical-disk activity
iostat -d -w 1
# Memory pressure and swap
sysctl vm.swapusage
memory_pressure
vm_stat 1
# Time Machine and FileVault
tmutil status
fdesetup status
# Thermal/performance warnings
pmset -g therm
A useful external trace
A public sustained-write trace from another APPLE SSD AP0512Z also showed high, intermediate, and low write-speed regions, with its first major transition around 90 GiB:
That test used 4 KiB writes and periodic file synchronization, so its absolute throughput should not be compared directly with the local 1 MiB uncached test. Its transition pattern nevertheless agrees with the local result.
After the test
- All temporary benchmark files and directories were deleted.
- Available space returned to approximately 266 GiB.
- No Data-volume snapshot retained the test file.
- SMART remained verified.
- TRIM remained enabled.
- No thermal or performance warning was recorded.
- No persistent system setting was modified.