ext4 vs XFS vs Btrfs: Choosing a Filesystem for a Server
The default filesystem your distro picks is not always the right one for your workload. Here is what actually differs and when each one wins.
Key takeaways
- The default filesystem your distro picks is not always the right one for your workload.
- Here is what actually differs and when each one wins.
On this page
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#
$ 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.
Get the DevOps Troubleshooting Cheat Sheet
Subscribe and get our free one-page reference for the errors that eat an afternoon — CrashLoopBackOff, OOMKilled, Terraform state locks, and more — plus new guides as we publish them.
More from Linux
Explore more articles in this category
journald Log Management: Retention, Filtering, and Forwarding
journald is the default log sink on every systemd distro, and most of it runs on defaults nobody chose. Here is how to actually control it.
DNS Troubleshooting on Linux: A Systematic Approach
\"It's always DNS\" is a joke because the failure modes are so scattered: resolver config, caching, search domains, split DNS. Here is where to actually look.
Resizing a Linux Filesystem Live with LVM (No Downtime)
The disk is full and the app is still running. Here is how to grow a logical volume and its filesystem underneath live workloads, safely.
You might have missed
Evergreen posts worth revisiting.