Filesystem Wars: Why Your Choice of Storage is Actually a Security Move

33 min read Original article ↗

While this post isn’t part of my ‘Canonical Series,’ it serves to lay the groundwork for an upcoming instalment in my ‘Apple Defenses’ series.

We’ll be exploring file systems from a high-level perspective, skipping disk geometry and low-level parameters in order to focus on the core concepts behind the most widely used systems, their overall design, and their respective strengths and weaknesses.

Enter the arena

We will be focusing on the following filesystems.

Filesystem Role
FFS / FFS2 (Fast File System) The noble ancestor
BFS (Be File System) The forgotten innovator
NTFS (New Technology File System) An industrial standard
ext4 (Fourth Extended Filesystem) Linux’s reliable workhorse
ZFS (Zettabyte File System) The champion of data integrity
APFS (Apple File System) Our main character

In memoriam - ReiserFS

I used this one extensively back in my “Linux fanboy era”—a phase that, fortunately, is long behind me. The community has essentially deprecated it, and for reasons that have nothing to do with code.

Among sysadmins, there’s a grim, recurring mantra: “ReiserFS is the only filesystem capable of making files disappear without a trace… just like its author did with his wife.”

Sic transit gloria mundi — Ford Transit Gloria Guida.

THE FUNDAMENTAL PROBLEM: Crash Consistency

Filesystem operations are not atomic at the hardware level. Creating a file involves multiple disk writes: allocate blocks, write data, create inode, update directory entry.

If the system crashes mid-operation, you can end up with orphaned blocks (space leak), dangling pointers (corruption), or directory entries pointing to garbage.

Every filesystem must solve this. Two classic solutions:

Journaling (NTFS, ext3/ext4): Write-ahead logging. Write intended changes to a journal first, then apply them to the filesystem. If a crash occurs, replay the journal. The cost: metadata is written twice (journal + final location).

Soft updates (FFS/FreeBSD): Track metadata dependencies and enforce write ordering. Never write a pointer before the thing it points to exists on disk. If a crash occurs, the filesystem is always consistent; worst case is a space leak, which background fsck reclaims. The cost: none (single writes).

We will see both approaches in action below.

FFS/FFS2

UFS, the old Unix filesystem, kept metadata and data far too far apart. Inodes lived near the beginning of the disk, while data blocks were pushed toward the end. The result was obvious: read inode, seek; read data, seek again; repeat. On spinning rust, this was performance hell.

FFS solved that problem with one of the most important ideas in filesystem history: cylinder groups. Instead of treating the disk as one monolithic space, it split it into smaller regions and gave each of them its own local inode table, local data blocks, and a backup copy of the superblock. In plain English: keep related things physically close. Put files near their metadata, keep related files near each other, and replicate critical metadata so recovery remains possible if one copy gets corrupted.

That alone was a huge step forward. It reduced seek times dramatically, improved locality, and established a pattern that influenced basically every serious Unix filesystem that came after it. ext4, ZFS, APFS: different worlds, different philosophies, but all of them live downstream of ideas that FFS helped define back in 1984.

So, if I had to compress its philosophy into one sentence, it would be this:

Simple, reliable, UNIX-native fundamentals — no feature bloat, just solid engineering.

Key architecture

The heart of FFS is still cylinder groups: metadata and data are kept close to each other, related files are often placed in the same region, and superblock redundancy gives the filesystem a chance to recover even when part of the disk goes bad.

Where things get particularly elegant is with soft updates, a major FreeBSD innovation. Instead of journaling every metadata operation, FFS tracks metadata dependencies and enforces the only rule that really matters: never write a pointer before the thing it points to exists on disk.

When creating a file, the dependency chain looks like this:

Creating a file is not one operation but a dependency chain: first the blocks must exist and be marked as allocated; then the inode may point to them; only after that may the directory entry link the filename to that inode.

This ordering matters because it determines what happens if the system crashes halfway through the operation.

If the crash occurs after blocks have been allocated, but before anything points to them, the result is simple: some blocks are marked as used, but no inode references them. That is a space leak, not corruption, and fsck can reclaim the leaked space later.

If the crash occurs after blocks have been allocated and data has been written, but before the inode exists, the situation is still the same in practical terms: leaked space, no structural corruption.

If the crash occurs after the inode has been created, then the inode points to valid data blocks, but no directory entry references it yet. In other words, the file exists, but it is orphaned. fsck can recover it by linking it into lost+found/, or remove it if needed.

If the crash occurs after the directory entry has been updated, then the operation is complete and the file is fully visible. No recovery is needed.

That is the beauty of soft updates: no journal, no double writes, no need to replay intent logs just to get back to a sane state. The filesystem remains consistent because write ordering prevents invalid references from ever reaching disk.

The tradeoff is equally clear: recovery is not as immediate as with journaling. You may still need fsck in the background to reclaim leaked space or clean up orphaned objects. But the key point is that the filesystem does not collapse into corruption.

UFS2 extends this design without betraying it: 64-bit support, larger filesystems, larger files, extended attributes, POSIX.1e ACLs, and larger inodes. Evolution, not reinvention.

Then there are the flags, which remain one of the nicest BSD touches: chflags immutable can prevent modification even by root, while chflags sappnd gives you append-only semantics that are still genuinely useful for logs and operational hardening. Nothing magical, nothing cryptographic, just simple kernel-enforced constraints that still matter.

Security model

The security model is classic BSD pragmatism.

POSIX permissions provide the standard user/group/world (rwx) access model.

ACLs, in UFS2, add finer-grained control through POSIX.1e semantics.

Flags such as immutable, append-only, and nodump go beyond plain POSIX permissions and give the administrator a few extra levers that are small, simple, and surprisingly effective.

What FFS/UFS2 does not provide is native encryption. On BSD systems, encryption is handled below the filesystem layer: on FreeBSD, that typically means GELI or, historically, GBDE.

Operational assumptions

FFS/UFS2 was designed for BSD systems: FreeBSD, OpenBSD, NetBSD.

Its assumptions are old-school and very clear: reliability matters more than flashy features, and consistency matters more than novelty. Soft updates give it crash safety without the overhead of full journaling, which is exactly the kind of engineering tradeoff BSD people tend to appreciate.

Portability, on the other hand, is not really its game. Outside the BSD world, UFS support exists mostly as a compatibility story, not as something people seriously build modern systems around.

Weaknesses

Its weaknesses are exactly what you would expect from a design with roots in 1984.

There is no native encryption.

There is no CoW model, so fragmentation remains a fact of life, even if the layout is smarter than old UFS.

Snapshots exist only as bolt-ons in specific BSD environments; they are not a native, first-class mechanism in the ZFS or APFS sense.

And, of course, portability is limited: this is fundamentally a BSD filesystem, not a cross-platform citizen.

FFS is 42 years old. It predates Linux. It predates ext2. And yet, it still matters, because it defined what a serious Unix filesystem was supposed to look like.

Cylinder groups, soft updates, file flags: these are not random features. They are design patterns. Later filesystems either inherited them, adapted them, or reacted against them.

Is it cutting-edge? Obviously not. Does it offer ZFS-level integrity guarantees or APFS-style OS integration? No.

But it is still trusted by FreeBSD and OpenBSD for core system roles, and that tells you a lot. FFS did not win by being flashy. It won by being disciplined.

It taught filesystems how to be faster through locality. It taught them how to stay consistent without drowning in complexity. And it did that without turning itself into a monster.

Respect the ancestor.

ZFS (Zettabyte File System) — Sun Microsystems / OpenZFS

We can formalise the philosophy of this filesystem as:

The filesystem IS the volume manager IS the RAID controller.

Key architecture

Pooled Storage: In ZFS, partitions are a thing of the past. You create a storage pool (zpool) and then “carve” datasets or volumes out of it as needed.

Copy-on-Write (CoW): This is the core engine. The file system never overwrites data in place; it writes new blocks and updates pointers atomically, ensuring consistency.

End-to-End Checksums: Every block is checksummed, and that checksum is stored in the metadata that references the block rather than inside the block itself. Every read operation can therefore be verified independently.

Snapshots & Clones: Thanks to CoW, snapshots are nearly “free” (low overhead). You can keep them indefinitely, and cloning is as simple as creating a writable branch from a snapshot.

Self-Healing: If configured with RAID-Z or mirrors, ZFS automatically detects bit rot via checksums and repairs the corrupted data using a healthy copy.

Security model

Data Integrity: This includes protection against silent corruption, integrity verification through end-to-end checksums, and near-instant recovery through snapshots and rollback.

In more detail, ZFS stores block checksums in the metadata that points to those blocks, creating a hierarchical chain of verification across the tree. This is not a substitute for a formal digital signature, but it provides a robust mechanism for detecting corruption and certain forms of unauthorized modification.

Encryption: Added later in the development cycle (notably in OpenZFS), encryption was not part of the original Sun Microsystems design. It operates as block-level encryption with external key management, allowing for encrypted datasets that can be replicated even without the host knowing the key (blind replication).

Access Control: ZFS provides no granular access control at the filesystem layer itself; it relies entirely on standard POSIX permissions (or ACLs depending on the OS implementation).

Operational assumptions

Designed for servers/NAS with large storage pools, ECC RAM (recommended), and multiple disks.
Expects you to care about data integrity over decades.
Not plug-and-play: you do not just format a random disk and mount it elsewhere. Pool metadata is complex.

Weaknesses

RAM-hungry (ARC cache).
Linux support = third-party (licensing issues with kernel).
Overkill for single-disk laptops.

It’s my default choice on FreeBSD. I am not a FOSS crusader, and I couldn’t be arsed with all that licensing rubbish; therefore in my case the pros outweigh the cons. Whilst I think it’s overkill for laptops, my FreeBSD laptop still uses it :)

BFS (Be File System) — BeOS / Haiku

The philosophy of this file system was simple yet revolutionary:

Metadata isn’t just storage overhead. It’s queryable data.

Let’s address the elephant in the room: when I first saw BeOS back in 1997, I immediately fell in love with it. I still miss it—not in a misty-eyed, nostalgic way, but in a “they solved problems in 1997 that everyone else ignored for 20 years” kind of way.

BFS treated metadata as first-class citizens. You didn’t just grep filenames or rely on fragile directory hierarchies. You queried the file system like a database:

“Show me all MP3s where Artist contains ‘Sabbath’ and Bitrate > 256kbps.”

The file system answered instantly. No heavy indexing daemons, no Spotlight-style background crawlers eating your CPU. The file system WAS the index.

Key architecture

Journaling: Metadata journaling for crash recovery (relatively novel for 1997).

Attributes: Arbitrary key-value metadata on files (not just POSIX extended attributes: BFS could actually query them).

Live Queries: Real-time FS queries updated automatically as files changed.

B+ Trees: Core structures relied on B+ trees, which helped BFS scale efficiently and suited the media-heavy workloads BeOS cared about.

Here some further notes deserve their own space:

  1. Live queries (the magic touch): If you had a folder (read - a saved query) that showed all incoming mails from James and a new mail from James came in, it would appear in the folder automatically. No refresh, no lag. The “dynamic folder” concept done well. 30 years ahead of its time.
  2. B+ Trees: interestingly, BFS used B+ trees for attributes, not only for files. That’s why queries were almost instantaneous: the system was not scanning a disk - it was an efficient visit on a balanced, pre-indexed tree.
  3. A note: relation with APFS - Dominic Giampaolo, the author of BFS, joined Apple after Be closed their doors. He’s been one of Spotlight’s lead engineers and worked extensively on APFS.

Security Model

Sadly, the security model of BFS was minimal:

  • POSIX permissions (user/group/world), nothing more.
  • No encryption.
  • No ACLs.
  • No advanced security features.

This is understandable: BeOS was designed for multimedia performance, not enterprise security. And we are talking about the late 1990s, when security was rarely front and centre.

Operational Assumptions

BFS was designed for BeOS/Haiku (desktop OS, multimedia-focused), and optimized for low-latency media access (video editing, audio production).

Journalists at trade shows would boot BeOS on a BeBox and play eight simultaneous video streams. Jaws dropped.

Weaknesses

Let’s be clear: this should be seen as a research-ish filesystem. If you approach it from that angle and focus on its strengths, it becomes a great source of ideas.

The truth of the matter is that BeOS died in 2001. Palm bought the corpse for a while. Haiku keeps BFS alive, but it’s a hobbyist OS.

The lack of modern security and portability already makes this filesystem an interesting case study, but not a viable alternative.

Be, Inc. had it right: filesystems aren’t just block allocators; they’re application platforms.

BFS proved that metadata queries could be fast, intuitive, and part of the user experience rather than bolted-on search tools.

Apple didn’t copy BFS (they barely acknowledged it existed), but they learned the same lesson 20 years later: the filesystem is part of the OS identity, not just infrastructure.

I still miss BeOS. But APFS is the closest thing to a spiritual successor—not in features, but in philosophy.

NTFS

I am not a Windows guy, but NTFS still deserves its tribute. It has been carrying most of the personal computing world for more than thirty years. It predates the web browser. It was designed when 1 GB hard drives were cutting-edge and Windows NT still ran on RISC workstations. And yet, in 2026, it is still the default filesystem on ordinary Windows systems. Microsoft tried to push ReFS as the future, but NTFS is still what normal Windows machines actually run. Some technologies age gracefully. NTFS just refuses to retire.

Its philosophy is something like:

Enterprise filesystem built for IT departments that need ACLs, audit trails, and endless backward compatibility.

Or, less politely:

What happens when you design a filesystem to satisfy legal compliance and still run software from 1993.

Whatever. Let’s pay respect to NTFS anyway.

Key Architecture

MFT (Master File Table): Everything is represented as a file, including metadata. The MFT is effectively a giant database of file records.

Journaling: Logs metadata changes for crash recovery.

Not CoW: NTFS overwrites in place; the journal records intent and metadata updates.

Alternate Data Streams: Files can contain multiple streams beyond the main unnamed one. Legitimate feature, excellent hiding place, and therefore catnip for malware.

ACLs: Fine-grained permissions with allow/deny entries, inheritance, and auditing.

EFS / BitLocker: Per-file encryption with EFS, full-volume encryption with BitLocker.

Security Model

ACLs: Powerful, flexible, and borderline Byzantine. Deny rules, inheritance chains, audit entries, the whole cathedral.

EFS: Per-file encryption tied to user certificates. Functional, but awkward. Recovery agents exist, key management is very Windows, and it can become painful when profiles or certificates go sideways.

BitLocker: Full-volume encryption, usually TPM-backed. Separate from NTFS in architectural terms, but it is the encryption layer that actually won on Windows.

USN Journal: Persistent change log useful for forensics, backup, and monitoring.

Operational Assumptions

NTFS is built for Windows desktops and servers.

It expects NTFS-aware tooling: chkdsk, defrag, the Windows permissions model, and the usual Microsoft admin machinery.

It is only partially portable. Linux can handle it with external drivers such as ntfs-3g; macOS traditionally exposes it as read-only unless you go out of your way.

Weaknesses

The expected ones.

Fragmentation: No CoW means files can scatter over time. Defragmentation mitigates it; SSDs make it less visible, but the design is still old-school.

No native snapshots: Volume Shadow Copy is an OS service, not a filesystem-native mechanism in the ZFS/APFS sense.

EFS: Still there, still usable, but clearly overshadowed by BitLocker and much more fragile operationally.

Proprietary: Microsoft has published a fair amount, but the ecosystem still carries enough opacity to keep reverse engineers employed.

Complexity overhead: ACLs, ADS, reparse points, legacy semantics. More features, more weirdness, more attack surface.

NTFS is the filesystem nobody loves and everybody uses. It is over-engineered for edge cases most users will never hit, yet somehow still full of compromises.

It fragments like it came from another century. EFS exists, but BitLocker won the encryption war long ago.

But here is the thing: it works. Billions of Windows machines run NTFS without catastrophic drama. It is boring, legacy-laden, and inelegant, but reliable enough for enterprise reality. I would not choose it if I had a real choice.

But if you live in Windows-land, it is not the worst prison.

Ext4

I discuss ext4 together with NTFS because, to me, they feel oddly similar. I know many Linux fanboys will send ninjas to my house to kill me, and I have probably already received three fatwas from the Holy Linux Inquisition, led by Mr. Stallman and the Seven Dwarves, for the previous sentence. I don’t really care.

ext4 is Linux’s default answer to “what filesystem should I use?” It is not exciting. It does not chase paradigm shifts. It just works, predictably, across millions of deployments.

As the fourth iteration of the Extended Filesystem lineage (ext2, ext3, ext4), it represents evolutionary refinement rather than revolutionary redesign. Think of it as the Toyota Camry of filesystems: boring, reliable, and nobody ever regrets choosing it.

It shipped in 2008 with kernel 2.6.28, which makes it 18 years old in 2026. Not ancient like FFS, not cutting-edge like APFS, just… dependable.

So, to honour the structure of this post, let’s get to the philosophy. Let’s say ext4 is:

The iterative workhorse: backward-compatible evolution focused on reliability over revolution.

Or, better still:

What happens when you take a solid foundation (ext2) and incrementally fix its problems for 20 years without breaking anything.

Key architecture

ext2 and ext3 relied on indirect block pointers. ext4, instead, moved to extents: contiguous ranges of blocks described as something like (start_block, length). This brings several advantages: less metadata overhead, better large-file performance, and reduced fragmentation.

Journaling is inherited from ext3. ext4 still has no native CoW: it overwrites in place, while the journal records metadata changes and ordering semantics. It offers three journaling modes:

  • data=journal (safest, slowest — journals both metadata and data)
  • data=ordered (default — journals metadata, but forces data blocks out before the related metadata is committed)
  • data=writeback (fastest, least safe — journals metadata only, with no ordering guarantees for data writes)

Still on CoW: the lack of native Copy-on-Write means no cheap clones, no native snapshots, and no automatic deduplication.

Delayed allocation: block allocation is postponed until writeback. Dirty data accumulates in memory, allowing the filesystem to batch writes and choose optimal block placement before committing to disk. The upside is better block placement, less fragmentation, and often fewer writes. The downside is that a crash can still lose recently written data before commit. Journaling helps with consistency, but it does not magically turn ext4 into CoW. Journaling has overhead — every metadata change is written twice (once to journal, once to final location). This is the price of crash safety. Note also that data=journal disables delayed allocation.

ext4 can grow a filesystem while mounted via resize2fs, and filesystems can also be shrunk while unmounted. There is also e4defrag for defragmentation — rarely needed, but it exists.

We mentioned snapshots. ext4 has no native snapshot facility, unlike ZFS or APFS. LVM can provide snapshots, but that is OS-level plumbing, not a filesystem-native feature.

Security model

POSIX permissions + ACLs: standard Linux access control with user/group/world (rwx) permissions, plus optional ACLs via setfacl/getfacl when finer-grained control is needed. Solid, unsurprising, and good enough for most Unix-like workloads.

The filesystem also supports native encryption via fscrypt, introduced for ext4 in the Linux 4.1 timeframe. This is directory-tree-based encryption rather than full-disk encryption: you apply a policy to a directory, and the files and subdirectories under it are protected accordingly. Keys live in the kernel keyring, not on disk. A typical use case is protecting user data at rest, for example under /home.

Its obvious limitation is that this is not the same thing as full-volume encryption: some filesystem metadata remains visible (directory structure, file count), and without the key, filenames appear as base64-encoded ciphertext rather than readable names.

From a security standpoint, ext4 also offers two simple but useful features: immutable and append-only flags:

  • chattr +i (immutable — cannot modify, delete, or rename)
  • chattr +a (append-only — can add data, cannot modify existing content)

These provide basic tamper resistance. Nothing cryptographic, just kernel-enforced constraints.

Operational Assumptions

ext4 is designed for Linux servers and desktops.

It is still the default choice in many Linux environments, and very much the expected baseline in the Debian/Ubuntu world. Fedora Workstation moved to Btrfs long ago, and RHEL prefers XFS, but ext4 remains the boring, familiar standard Linux admins know by heart.

Standard Linux tooling (e2fsck, tune2fs, resize2fs, e4defrag) is part of the deal.

Portability

  • Linux-native (obviously)
  • Windows: third-party drivers and tools exist
  • macOS: readable via third-party tools and FUSE-based solutions
  • Not plug-and-play outside Linux

Other weaknesses

We already covered the CoW-related trade-offs and the fragmentation angle, even if ext4 mitigates both reasonably well.

Another thing I personally miss: ext4 journals metadata, but it does not provide end-to-end integrity checking for file data in the ZFS/APFS sense. Metadata checksums exist, but silent corruption in file contents is still a real possibility.

Remember when I said ext4 and NTFS feel oddly similar? This is the reason.

They solve the same class of problems in roughly the same conservative way. Both are journal-based. Both overwrite in place. Both can fragment, although ext4 handles that a bit more gracefully through delayed allocation. Encryption arrived late in both worlds: EFS and BitLocker on the NTFS side, fscrypt on the ext4 one. And neither gives you native snapshots; if you want those, you go outside the filesystem itself—VSS for Windows, LVM for Linux.

In other words, both are defaults built for the real world: legacy constraints, predictable behaviour, and minimal drama. Architectural purity was never the point.

The real difference is cultural. ext4 evolved incrementally and in the open, through the gradual evolution of ext2, ext3, and ext4. NTFS evolved by Microsoft decree, accumulating thirty years of Windows baggage along the way.

Different ecosystem, different politics, similar result: dependable, boring, and exactly what millions of users need.

ext4 is what you get when you evolve carefully instead of revolutionising recklessly. It is not sexy. It does not have ZFS’s checksums or APFS’s sealed-volume theatrics. It fragments, although delayed allocation helps. It lacks native snapshots.

But here is what it does have: years of production hardening, predictable behaviour, and boring reliability. When you run apt install on a Debian server, you are not thinking about filesystem philosophy. You are thinking: “will this still work in five years?” ext4’s answer is usually yes.

I would not choose it for a NAS; ZFS wins there. I would not choose it for a laptop where tight OS integration matters; APFS wins there. But for a Linux server that just needs to serve files reliably, ext4 is still the safe bet.

Nobody ever got fired for choosing ext4.

APFS

No comparison of modern filesystems would be complete without APFS — the Apple File System.

The reason I dragged all the others onto the stage first is simple: I wanted a map of the landscape before focusing on Apple’s answer to it. For this blog, what matters is not just how the wider IT world solves storage problems, but how Apple chooses to solve them — and, more importantly, how those choices shape the security model of the platform.

That is why this long detour was necessary. To understand APFS properly, one must first understand what came before it, what problems other filesystems tried to solve, and what tradeoffs they embraced. Only then does it become possible to appreciate how deeply Apple built parts of its modern system architecture and defensive model around APFS.

Broadly speaking, traditional filesystems tend to live inside a relatively rigid storage layout. You start with a disk, carve it into partitions, and then create a filesystem inside each partition. Each partition has a fixed size unless you explicitly resize it, and each filesystem tends to consume the space assigned to it. This model works, but it is static, awkward to resize, and not especially elegant once multiple operating systems, recovery partitions, or encrypted containers enter the picture.

What the operating system actually mounts and uses are volumes or filesystems exposed through that structure. Those volumes are logically separate, and that separation is usually enforced by partition boundaries or by some additional abstraction layered on top.

APFS takes a very different path.

The Container Model

Instead of carving a disk into rigid, fixed-size partitions, APFS introduces the idea of a container. The closest rough analogy is a storage pool: not unlike a ZFS zpool, but designed for Apple’s world of single-disk systems — laptops, desktops, phones, tablets — rather than multi-disk servers.

A physical disk or SSD can hold one or more APFS containers. Inside each container live one or more volumes. These are not traditional fixed-size partitions. They share the available space dynamically from the container’s common pool.

Example: a 500 GB SSD might contain a single APFS container with three volumes:

  • System (the macOS read-only system volume)
  • Data (user data, writable)
  • Preboot (boot support files)

All three volumes draw from the same 500 GB pool. If the System volume needs 15 GB and the Data volume needs 300 GB, that is what they take — without pre-allocation, without rigid boundaries, and without manual resizing. Free space is shared across the container.

The importance of this approach is obvious if we think back to the old partition-resize mess: ext4, NTFS, moving boundaries around, hoping nothing went wrong, and sometimes losing data in the process. APFS removes that entire class of stupidity. You do not resize volumes in the old sense. They simply consume space from the container until that shared pool is exhausted.

This is a familiar idea in spirit: ZFS arrived at it in one direction, Apple in another. But APFS applies it with a very specific goal in mind — making modern storage layouts more flexible, less awkward to manage, and better suited to consumer devices.

Copy-on-Write (CoW)

Like ZFS, APFS is a copy-on-write filesystem. That means it never overwrites old data in place. When something changes, APFS writes the new version to fresh blocks, updates the relevant pointers, and only later frees the old blocks.

This approach changes the entire failure model. If the system crashes halfway through a write, the old data is still there. The new data may be incomplete, but the filesystem never ends up in that ugly half-updated limbo that older in-place filesystems have to clean up afterwards.

It also means that snapshots are almost trivial. Since the old blocks remain valid until they are explicitly released, taking a snapshot is basically a matter of freezing the current pointer state. No wholesale copying, no long wait, no drama.

The same logic makes clones cheap. If you duplicate a file or directory, APFS does not immediately duplicate the data blocks. It duplicates the references. The blocks remain shared until one side changes, and only then does CoW step in and split the data.

Compared to ext4 or NTFS, this is a different world. Those filesystems overwrite in place, so snapshots require extra machinery such as LVM or VSS, and cloning means physically copying data. APFS gets both almost for free because CoW is part of the design, not an add-on.

Snapshots and Clones

In APFS, snapshots are read-only views of the filesystem at a specific point in time. Apple uses them extensively. Time Machine, for example, no longer has to rely on the old HFS+ hard-link gymnastics; APFS gives it native snapshot support.

Clones are equally practical. Duplicate a large file and the operation is nearly instantaneous, because APFS is not copying ten gigabytes block by block at that moment. It is just reusing what already exists. Only the modified blocks become new writes later on.

This turns out to be extremely useful for system updates. macOS can clone the system state, apply an update to that cloned state, verify that everything is coherent, and then switch boot targets atomically. If something goes wrong, the old state is still there.

Encryption

One of the biggest differences between APFS and older filesystems is that encryption was not bolted on later. It was part of the design from the start.

APFS supports per-volume encryption, which means different volumes inside the same container can be protected independently. On modern Apple systems, key handling is tied to hardware security components such as the Secure Enclave, whether that lives in a T2-equipped Intel Mac or in Apple Silicon.

Apple supports different encryption setups, from unencrypted volumes to single-key configurations and more granular schemes with per-file keys wrapped by higher-level volume keys, as used by FileVault.

This is a very different story from ext4 or NTFS. ext4 gained fscrypt years after ext4 already existed, and even then the model remained directory-tree-based rather than volume-wide. NTFS had EFS, which always felt awkward and fragile, and in practice BitLocker became the real answer. With APFS, encryption is not the weird optional feature lurking at the edge of the design. It is native, mature, and tightly coupled with the rest of Apple’s platform security.

Space Efficiency

APFS is also much smarter than old-school partition thinking.

Volumes inside the same container share free space dynamically, so you do not have to pre-allocate rigid sizes and then regret them later. Space goes where it is needed.

It also supports sparse files, where unallocated ranges do not consume physical storage, and it has some support for compression in Apple-specific contexts. This is not ZFS-style transparent filesystem-wide compression, but it is still part of how Apple squeezes efficiency out of storage for selected content and system resources.

Crash Consistency

Because APFS is built around CoW and atomic pointer updates, it does not need journaling in the old ext4/NTFS sense.

If a crash happens in the middle of a write, the old version of the data is still intact. The new version may be incomplete, but until the pointers are updated, the filesystem continues to reference the valid state. That is why APFS can usually mount immediately after a crash without the ritual of journal replay or the looming fear of a long fsck.

This is one of the cleanest consequences of the design. ext4 and NTFS need journals because they overwrite in place. FFS with soft updates keeps consistency through ordering rules, but may still need background cleanup. APFS takes a different route: no journal, no replay, no leaked-space cleanup dance. The consistent state is already there.

What APFS Learned

This is where all the previous filesystems become useful as background rather than as museum pieces.

From BFS, APFS seems to inherit a broad philosophical lesson: the filesystem is not just plumbing. It is part of the identity of the operating system. APFS does not expose metadata queries in the BeOS sense, but it absolutely behaves like a core platform component rather than a silent storage backend.

From ZFS, the inheritance is more concrete: CoW, snapshots, space sharing, and the idea that storage layout should be fluid rather than trapped inside rigid partition boundaries. But Apple adapted those ideas to a very different target. ZFS was built with servers and large storage systems in mind. APFS was built for laptops, phones, tablets, and tightly integrated consumer devices.

From FFS, APFS inherits a more general discipline: reliability matters, and a filesystem should solve real problems without degenerating into a monster. Apple did not copy BSD’s solutions directly, but the same taste for pragmatic engineering is visible.

And from ext4 and NTFS, APFS mostly learned what to avoid: in-place overwrites, bolted-on encryption, external snapshot machinery, and the general feeling of dragging decades of compatibility baggage into a world that no longer matches the assumptions of spinning disks and static layouts.

Philosophy

Modern storage for modern devices: flash-optimised, encrypted by default, copy-on-write native, and designed as part of the OS security model.

Or, more bluntly:

What happens when you design a filesystem for 2017 rather than 1997, and assume SSDs, Secure Enclaves, and platform hardening are simply part of the deal.

Operational Assumptions

APFS is designed for Apple devices: Macs, iPhones, iPads, Apple Watches.

It assumes flash storage first. That does not mean it cannot exist on spinning disks, but its design clearly belongs to the SSD era: allocation strategy, cloning behaviour, snapshots, and general expectations all fit modern solid-state storage far better than old mechanical media.

It also assumes the Apple ecosystem around it: Secure Enclave-backed key handling, tight kernel integration, SIP, Sealed System Volumes, and the rest of the platform security stack.

And, of course, it assumes you are living in Apple-land. APFS is not a portable filesystem in the cross-platform sense. Outside macOS and iOS-family systems, support is limited and usually partial.

Weaknesses

APFS is not magic.

It is closed-source, which means that deep understanding often depends on reverse engineering, experimentation, and reading between Apple’s lines. But we’re not OSS crusaders, so we can deal with this.

It does not self-heal the way ZFS can when redundancy and checksums are combined. If a block goes bad, APFS can detect problems in some contexts, but it will not magically reconstruct damaged data for you. Backups still matter.

It is also a young filesystem compared to old warhorses such as FFS, ext4, or ZFS. It shipped in 2017. That is enough time to be real, but not enough time to carry the same historical weight as filesystems that have been beaten up in production for decades.

And finally, it is Apple-only in any practical sense. That is not a technical flaw so much as a strategic choice, but it still matters.

APFS is Apple’s answer to a simple question: what would a filesystem look like if you designed it for the hardware and threat model of the modern Apple ecosystem rather than for the compromises of the 1990s?

It assumes flash storage instead of spinning rust. It assumes encryption is normal, not exotic. It assumes snapshots and clones should be native features, not awkward external tricks. And it assumes the filesystem is part of system hardening, not just a place where bytes happen to live.

That is why APFS feels different. It does not just store files competently. It participates in how Apple secures the platform.

Is it perfect? Obviously not. It is closed, young, Apple-specific, and less transparent than many of its predecessors. But it is also purpose-built for what Apple actually needed: a filesystem that works hand in glove with hardware-backed key management, operating system hardening, atomic updates, and modern device workflows.

In Part 2, we will look at the consequence of that choice: APFS is not just a storage layer. It is one of the building blocks of macOS hardening, through mechanisms such as Sealed System Volumes, firmlinks, and the broader logic of system integrity.

BFS made the filesystem a user experience layer.
ZFS made it a data integrity layer.
APFS makes it a security boundary.

The tables that Google loves sooooo much when indexing your website

Overall comparison

Feature ZFS APFS NTFS FFS/FFS2 ext4 BFS
Copy-on-Write Yes Yes No No No No
Snapshots (native) Yes Yes No Bolt-on No No
Encryption (native) Later Yes EFS No fscrypt No
Checksums (data) Yes Metadata No No No No
Self-healing Yes No No No No No
ACLs POSIX+ macOS Windows UFS2 Linux Basic
Portability BSD/Linux macOS Partial BSD Partial Haiku
Use case NAS/Server Apple devices Windows BSD servers Linux default Multimedia

Conservatively estimated failure rate (my bullshit math)

Filesystem Resize Operation Estimated Failure Rate (Data Loss)
ext4 Grow (mounted) < 1% (well-supported, journaled)
ext4 Shrink (unmounted) 5-8% (higher risk, metadata relocation)
NTFS Grow (Windows DM) 2-5% (Microsoft tools are cautious)
NTFS Shrink (3rd party) 10-15% (unmovable files, fragmentation issues)
FFS/UFS Grow (growfs) < 1% (mature, stable)
FFS/UFS Shrink (manual) 30-40% (not officially supported)
FAT32 Any resize 15-20% (no journaling, brittle metadata)

Comparison ages

Filesystem Release Year Age (2026)
FFS 1984 42 years
NTFS 1993 33 years
BFS 1997 29 years (but BeOS died 2001)
ZFS 2005 21 years
ext4 2008 18 years
APFS 2017 9 years

Soft Updates vs. Journaling vs. CoW

Aspect Soft Updates Journaling CoW (ZFS/APFS)
Write Overhead 1x (single write) 2x (journal + final) 1x (new blocks only)
Crash Consistency Always consistent Always consistent Always consistent
Recovery Time Instant mount + background fsck Instant (journal replay) Instant (no fsck needed)
Space Leaks Possible (reclaimed later) No No
Snapshots Bolt-on (FreeBSD) External (LVM) Native (free)
Complexity Medium (dependency tracking) Medium (journal management) High (CoW + snapshots)

Conclusions

This post lays out the groundwork for the next one: Apple Defences: the organisation of the filesystem. I simply couldn’t give those concepts without an introduction of what led Apple to make some choices. That post will be very hands-on!

See you next week. Until then, stay paranoid, and copy-on-write your notes.

Want to understand how attackers bypass these protections? I’m building a macOS Reverse Engineering course that covers SIP internals, APFS forensics, and Mach-O binary analysis. Get in touch with me on Mastodon (my handle being @gbiondo on infosec.exchange) or simply drop me an email to work@bytearchitect.io.