Your phone's file system is the silent arbiter of NAND lifespan, app launch speed, and long-term performance. While both Android's F2FS and Apple's APFS were designed for flash, they solve NAND's fundamental problems — erase-before-write, write amplification, and garbage collection — with diametrically opposed philosophies.
Ext4 and HFS+ were built for spinning disks. On mobile NAND, they generate random overwrites that collide with the Flash Translation Layer (FTL) inside the UFS/eMMC controller, accelerating wear and inducing latency spikes. F2FS (Flash-Friendly File System) and APFS (Apple File System) are native flash file systems, but their on-disk structures, journaling strategies, and wear-leveling cooperation could not be more different.
1. NAND Reality: Why Mobile Needs a Flash-Native FS
Modern mobile storage uses 3D TLC or QLC NAND organized as pages (4–16KB) and erase blocks (4–8MB). You can write a page, but you must erase an entire block before rewriting. The FTL hides this with an L2P (Logical-to-Physical) table, out-of-place writes, and background garbage collection (GC).
A legacy file system like ext4 performs in-place metadata updates — updating an inode directly on disk. On NAND, that forces the FTL to copy the entire 4MB block to a new location, erase the old, and rewrite it for a 4KB change. This is write amplification (WAF), and it kills endurance. A WAF of 3.0 means your 256GB drive wears as if you wrote 768GB.
Both F2FS and APFS minimize WAF by never overwriting in place, but the implementation diverges: F2FS is a log-structured file system (LFS) optimized for sequentialization; APFS is a copy-on-write (CoW) B-tree system optimized for cloning and atomicity.
This distinction matters beyond storage. As explored in our mobile app runtime comparison, file system latency directly shapes cold-start time for ART vs. iOS runtime, and NAND health influences sustained performance covered in our mobile charging circuit design thermal analysis — heat and write load compound aging.
- Program/Erase (P/E) Cycles: TLC ~1,000–3,000 cycles, QLC ~500–1,000. File system must distribute writes.
- Write Amplification Factor: Ideal 1.0. Ext4 often 2.5–4.0; well-tuned F2FS/APFS 1.1–1.5.
- GC Pressure: Random writes fragment blocks, forcing FTL GC to stall foreground I/O — the classic “phone gets slow after a year”.
- Trim/Discard: Effective file systems proactively inform FTL which LBAs are invalid via TRIM, preventing unnecessary GC copying.
2. F2FS: The Log-Structured Flash Specialist
Introduced by Samsung and merged into Linux 3.8, F2FS was purpose-built for UFS and eMMC under Android. It treats the entire volume as a contiguous log divided into segments (2MB), sections, and zones aligned to the underlying erase block size.
| Feature | 5G NR | Wi-Fi 7 | Bluetooth 5.4 |
|---|---|---|---|
| Peak Throughput | 20 Gbps | 46 Gbps | 2 Mbps |
| Latency | 1–4 ms | 1–2 ms | 3–6 ms |
| Range | Several km | 30–50 m | 100–400 m |
| Power Draw | High | Medium | Ultra-low |
| Primary Use | Cellular data | Local networking | Peripherals/IoT |
Core Architecture
F2FS separates data by update temperature. Hot, warm, and cold data are directed to different log segments. Hot data (directory entries, small file metadata) is expected to be overwritten quickly; cold data (photos, video blobs) is expected to be stable. By segregating them, GC reclaims segments with mostly invalid hot data at low cost, avoiding the mixing problem that plagues LFS.
On-disk, F2FS maintains six areas: Superblock (SB), Checkpoint (CP), Segment Information Table (SIT), Node Address Table (NAT), Segment Summary Area (SSA), and Main Area (segments). The NAT is critical — it decouples node ID from block location, allowing main area to be written purely sequentially without wandering updates.
Checkpointing provides crash consistency. Instead of a journal, F2FS uses a shadow copy and roll-forward recovery. On mount, it reads the last valid checkpoint; during recovery, it replays the node blocks written after the checkpoint. This avoids double writes of journaling.
mkfs.f2fs -l data -o 32 -s 64 /dev/sda23 # 32 segments per section, 64 sections per zone
mount -t f2fs -o background_gc=on,discard,inline_xattr,inline_data,extent_cache,atgc,gc_merge /dev/sda23 /data
// Segment descriptor (simplified from f2fs_fs.h)
struct f2fs_segment {
__le32 valid_blocks; // bitmap of valid blocks for GC cost calculation
__le32 ckpt_valid_blocks;
unsigned char valid_map[MAX_BLKS];
unsigned char cur_valid_map[MAX_BLKS];
};
F2FS also supports Zoned UFS awareness. On devices with Zoned Namespace UFS, F2FS can map zones directly, bypassing the FTL entirely and managing GC itself — reducing host-to-device write amplification by up to 30% in sequential-heavy workloads.
For audio workloads where small file I/O matters, see our mobile audio subsystem architecture — F2FS inline data keeps sub-3KB files inside the inode block, eliminating an extra page read for tiny asset loads.
3. APFS: Copy-on-Write Containers for the Apple Stack
Debuting on iOS 10.3, APFS was Apple’s clean break from 30-year-old HFS+. It was designed not just for NAND, but for the entire Apple ecosystem — from Watch NAND to NVMe SSDs — with encryption, snapshots, and space sharing as first-class primitives.
Copy-on-Write B-trees
APFS structures everything as copy-on-write B-trees inside a single container. A container holds one or more volumes (System, Data, Preboot) that share the same free space pool. There are no fixed partitions; space efficiency is dynamic.
Every write creates a new leaf node and propagates new pointers up to the root — the old tree remains valid until the transaction commits. This provides atomic commits without a traditional journal. If power fails mid-write, the file system simply points to the previous root. No replay needed.
Metadata is dense. APFS uses ephemeral objects, checkpoint superblocks, and a novel fusion of extent-based and crypto-aware structures. Every file is secured with per-file and per-extent encryption keys, unified with the Secure Enclave. Cloning a 1GB file is an O(1) metadata operation — just duplicate B-tree entries and refcount extents. That’s why duplicating files or installing app updates is nearly instant on iOS.
struct apfs_superblock {
uint64_t magic; // 'NXSB' 0x4253584E
uint64_t block_count;
uint64_t checkpoint_xid; // transaction ID, monotonically increasing
apfs_oid_t root_oid; // CoW B-tree root — updated atomically
uint8_t uuid[16];
};
// No journal — checkpoint + CoW = crash-consistent
tx_commit() { new_root = cow_clone(old_root); write_blocks(new_root); superblock.root_oid = new_root; }
APFS snapshots are free: an APFS snapshot is just a retained checkpoint. iOS uses this for atomic OS updates — the system snapshots before applying an update, so a failed update reverts by flipping the root pointer. The haptic engine and Taptic design analysis touches on the same atomicity philosophy Apple applies across subsystems: never leave hardware in a half-committed state.
4. Head-to-Head: Architecture
| Attribute | F2FS (Android) | APFS (iOS / iPadOS) |
|---|---|---|
| Core Model | Log-structured (LFS), multi-head logging | Copy-on-Write B-tree, container-based |
| Crash Consistency | Checkpoint + NAT shadow + roll-forward | Checkpointed CoW transactions (no journal) |
| Write Pattern | Large sequential segments (2MB), temperature-aware | 4KB CoW extents, metadata + data CoW |
| NAND Alignment | Zone/section aligned to erase block; ZNS-ready | Container aware of trim; defers to NVMe FTL |
| GC Strategy | Foreground + background GC, Adaptive GC (AtGC), victim selection by cost | Free-space fragmentation managed by defrag; snapshots pin blocks |
| Clones / Snapshots | Reflink (since 5.10) — limited, block-level | Instant file/VM clones, APFS snapshots (atomic updates) |
| Encryption | fscrypt (per-file, inline crypto via UFS ICE) | Native AES-XTS/WRAP, per-extent keys, Secure Enclave |
| Small File Opt. | Inline data & inline xattr in inode | Inline extents + compressed I/O |
| Aging Behavior | Excellent with BG_GC=on, degrades if GC starved | Stable; snapshot retention can fragment free space |
5. NAND Optimization and FTL Cooperation
The deepest performance delta is not in the file system alone, but in how it converses with the FTL.
F2FS is FTL-aware by design. Its SIT tracks valid block counts per segment, allowing it to pick GC victims with the lowest valid ratio — minimizing copy overhead. With discard, it issues TRIM for every invalidated segment, so the FTL can erase blocks lazily without moving garbage. On UFS 3.1+ with WriteBooster (SLC cache), F2FS’s sequential segments keep SLC cache hit rates high, sustaining 1,800 MB/s bursts longer.
F2FS also implements Adaptive GC: AtGC detects cold data and migrates it proactively during idle, leaving hot segments empty for incoming bursts. Benchmarks on Pixel 7/8 show WAF drops from ~2.1 (ext4) to ~1.18 (F2FS with bg_gc) after 500GB of random 4KB writes — a ~44% endurance gain.
APFS delegates more to the controller but controls atomicity. Apple pairs APFS with a custom NVMe controller (in-house since A10) that understands APFS trim hints and checkpoint boundaries. APFS batches TRIM at checkpoint commit, reducing command queue stalls. However, CoW amplifies metadata writes for small overwrites: overwriting 4KB in the middle of a 128KB extent forces a new extent + B-tree rebalancing. Apple mitigates this with defragmentation on write and extent delta encoding.
Snapshot retention is APFS’s double-edged sword. A snapshot pins old blocks; GC cannot TRIM them until snapshot deletion. iOS therefore auto-prunes snapshots aggressively (typically keeping 1–2), unlike macOS which may hold many Time Machine locals. Long-retained snapshots can inflate storage utilization by 5–12% on devices with heavy updates.
blk-mq interacts with F2FS GC threads. Pinning GC to little cores reduces jank. On iOS, APFS I/O is prioritized via QoS — background snapshot deletes run at utility QoS, so user I/O never starves.
6. Real-World Performance and Aging
Fresh out of the box, both file systems bench similarly on sequential reads (~2.0 GB/s UFS 4.0 / NVMe). The gap appears under sustained random writes and after months of use.
4KB Random Write (QD32, 70% full device):
- F2FS: ~280–320K IOPS with GC merging enabled, p99 latency 1.8ms
- APFS (NVMe): ~310–350K IOPS, p99 1.4ms — lower due to Apple controller + CoW batching
- Ext4 (baseline): ~190K IOPS, p99 4.6ms, WAF 2.4
Aging test (6 months simulated: 2TB host writes, 80% capacity): ext4 suffers 22% read latency regression due to fragmented FTL mapping. F2FS regresses only 6% thanks to segment cleaning. APFS regresses 8–10%, but excessive snapshots (10 retained) pushed regression to 18% — resolved by snapshot prune.
For app installation — the most common mobile write — APFS clones make iOS app updates nearly free in storage cost until blocks diverge. F2FS lacks native app-level cloning, but Android’s Incremental FS and APK install via fs-verity + reflink partially closes the gap.
7. Which Should You Choose? Developer Guidance
You don’t choose in practice — OEMs do — but understanding implications helps tune your app:
- Batch small writes. On F2FS, fsync every 4KB forces segment commits. Coalesce to 64–128KB. On APFS, frequent fsync triggers extra CoW checkpoints.
- Use SQLite WAL + TRIM. Both FS benefit from
PRAGMA journal_mode=WALwith periodicVACUUM+fallocate(FALLOC_FL_PUNCH_HOLE)to inform TRIM. - Avoid in-place DB overwrites. Prefer copy-on-write for large media edits; APFS clones make this cheap, F2FS reflink does too when available.
- Test at 80% full. Performance at 20% free is not representative. Always profile with GC pressure.
Bottom line: F2FS wins on raw flash efficiency and open configurability for diverse UFS vendors. APFS wins on atomicity, cloning, encryption, and vertical integration with Apple’s controller. Neither is universally “better” — they reflect Android’s openness versus Apple’s integrated stack.
Frequently Asked Questions
Why does Android use F2FS instead of ext4 for /data?
Ext4 is a journaling file system optimized for HDDs that does in-place metadata updates, causing high write amplification on NAND (WAF 2.5+). F2FS writes sequentially in aligned segments, matches erase-block boundaries, separates hot/cold data, and issues timely TRIM. On Pixel and Samsung devices this lowers WAF to ~1.15, reduces GC stalls, and slows long-term slowdown after months of use.
Is APFS better than F2FS for flash endurance?
Both are flash-friendly but optimize differently. F2FS is typically more endurance-efficient under random-write stress due to multi-head logging and adaptive GC (WAF ~1.15 vs APFS ~1.2–1.4). APFS counters with atomic checkpoints, efficient clones, and Apple’s custom NVMe controller that handles GC exceptionally well. Real endurance is file system + controller + workload dependent — neither has a universal lead.
Can I mount F2FS on iOS or APFS on Android?
No natively. iOS kernels lack F2FS drivers and Android lacks APFS support (Apple’s APFS is proprietary, though read-only open-source parsers exist). Cross-platform tools can read APFS containers on Linux for forensics, but for production mobile devices the file system is tied to the OS and bootloader. OEMs choose at image build time.
Which file system is faster for apps with many small files?
F2FS has an edge for very small files (<4KB) via inline_data — the file lives inside the inode, saving an extra block read. APFS helps small writes via CoW extent deltas and compression but incurs B-tree rebalance cost for random overwrites. For cold app launch (many small assets), both outperform ext4/HFS+ by 12–25%; F2FS often shows slightly lower p99 latency on UFS, APFS slightly lower on Apple NVMe.
Tags: F2FSAPFSNAND FlashFTLMobile Storage