ext4 vs XFS vs Btrfs: Choosing a Filesystem for a Server

Most servers run whatever filesystem their distro defaults to and never think about it again, which is usually fine, until a workload hits exactly the case where the default isn't the best fit. Ubuntu and Debian default to ext4. RHEL, CentOS, and Fedora default to XFS. openSUSE defaults to Btrfs for the root filesystem. None of those defaults were arbitrary, and none of them are universally correct for every workload you'll run on top.

What actually differs #

| ext4 | XFS | Btrfs
Maturity | Oldest, most battle-tested | Mature, RHEL default since 7 | Newest of the three, stable for single-disk use
Grow live (mounted) | Yes | Yes | Yes
Shrink | Yes, but unmounted only | No, not supported at all | Yes, live
Large-file / parallel I/O | Good | Excels, built for this | Good
Snapshots | No (needs LVM below it) | No (needs LVM below it) | Built in, no LVM needed
Checksums (data integrity) | Metadata only | Metadata only | Data + metadata
CPU overhead | Lowest | Low | Higher (checksumming, CoW)
Max practical size | Very large, well-tested at scale | Very large, excels at scale | Large, less battle-tested at extreme scale

The two decisions that eliminate an option outright, before performance even enters the conversation:

You might need to shrink this volume later → XFS is out. XFS cannot be shrunk under any circumstances, online or offline. If there's any chance a volume gets over-provisioned and needs to come back down, that alone rules it out.

You want snapshots without adding LVM underneath → ext4 and XFS are out. Neither has native snapshot support; you'd need LVM snapshots (see resizing a filesystem live with LVM) as a layer underneath either of them. Btrfs has snapshots built into the filesystem itself.

Where each one wins in practice #

ext4 is the safe, boring default for general-purpose workloads: a typical application server, a database that doesn't need filesystem-level snapshots, a home directory. It has the longest track record, the lowest CPU overhead, and the most tooling built assuming it exists. If nothing below pushes you toward a specific alternative, ext4 is a reasonable default precisely because it's unremarkable.

XFS wins decisively for large files and high-parallelism I/O: media storage, data warehouses, large log/analytics volumes, anything with big sequential writes across many threads. It was built by SGI specifically for high-throughput workloads and it shows in benchmarks on exactly that pattern. The tradeoff you're accepting is permanently: it can grow but never shrink, so provision conservatively or plan to migrate data rather than resize down.

Btrfs wins when snapshots, checksumming, or copy-on-write cloning are worth more to you than raw performance headroom. Instant, cheap snapshots before a risky package upgrade or config change (openSUSE's snapper integration does exactly this automatically), built-in data checksumming that catches silent corruption ext4 and XFS won't notice, and btrfs send/receive for efficient incremental backups. The cost is CPU overhead from checksumming and copy-on-write, and, for workloads with heavy random writes to large files like some database engines, fragmentation patterns that need active management (autodefrag, or excluding those files from CoW with chattr +C).

Checking what you're already running #

bash.bash

$ df -T /data
Filesystem Type Size Used Avail Use% Mounted on
/dev/mapper/vg_data-lv_data ext4 89G 50G 35G 57% /data

$ mount | grep " / "
/dev/sda2 on / type xfs (rw,relatime,attr2,inode64,...)

df -T is the fastest way to confirm the actual filesystem type on any mount. Don't assume it matches your distro's default, especially on a box someone else provisioned or one built from a custom image.

A real decision, not a benchmark chase #

Benchmarks between these three vary enormously by workload, kernel version, and mount options, to the point where chasing the "fastest" one in isolation is usually the wrong exercise. The decision that holds up is driven by the constraints above, in this order:

Will this volume ever need to shrink? If yes, XFS is disqualified immediately; don't discover this during an actual resize.

Do you want filesystem-native snapshots without adding LVM as another layer? If yes, Btrfs; otherwise ext4 or XFS plus LVM snapshots underneath.

Is the workload dominated by large sequential files and high parallel throughput (media, data warehousing, big log volumes)? XFS is the strongest default for that pattern specifically.

Everything else: ext4, and don't spend more time on it. The filesystem is rarely the bottleneck for a typical application workload, and ext4's maturity and low overhead make it a sound default when nothing above points elsewhere.

This decision compounds with your storage layer choice; see resizing a Linux filesystem live with LVM for how growing works on top of any of these three, and diagnosing disk full on Linux for the troubleshooting side once a volume is full regardless of which filesystem it's running.

The call we'd make #

Default to ext4 unless a specific requirement pulls you off it: XFS for large-file/high-throughput workloads where you're confident you'll never need to shrink the volume, Btrfs when native snapshots and checksumming are worth the CPU overhead. Check df -T before assuming; the box in front of you may already be running something other than what you'd have chosen.