Your Disk I/O Scheduler Might Be Actively Hurting Your Performance
Technical Briefing | 10/20/2026
You’ve checked CPU, memory, network, and everything looks fine on `top` or `htop`. Your application containers seem to have enough headroom. But that database query is still taking just a bit too long, or those log writes are introducing a weird stutter you can’t quite pinpoint. Often, when the usual suspects are cleared, the problem’s hiding deeper in the I/O stack. And more often than you’d think, the default I/O scheduler is either not helping or actively making things worse.
What’s the Kernel Actually Doing Down There?
When an application asks for data from disk, it doesn’t just happen instantly. The kernel’s block layer queues these requests, and an I/O scheduler decides the optimal order to send them to the actual storage device. Its job is to minimize seek times on spinning disks, ensure fairness across different processes, and generally improve throughput or reduce latency. Most folks just let it run on default, and for a long time, that was `CFQ` (Completely Fair Queuing) or `deadline` on older systems. Modern kernels mostly use `mq-deadline` or `bfq`.
Why ‘noop’ Isn’t Always the Silver Bullet for SSDs
The common wisdom for SSDs or NVMe drives is to switch the I/O scheduler to `noop`. The logic is sound: SSDs don’t have physical read heads that need seeking, so why bother with a scheduler trying to optimize for seeks? Just pass the requests straight through. And often, that’s absolutely the right move. But here’s where it gets nuanced: if your hardware RAID controller or even your NVMe controller already has its own sophisticated scheduler, `noop` just means you’re potentially bypassing a better-optimized path. I’ve seen `noop` make things worse when the application’s I/O patterns were erratic and the controller needed more hints. You also have to consider what kind of I/O you’re dealing with – large sequential reads for backups, or tiny random writes for a transactional database?
cat /sys/block/sdX/queue/scheduler
echo mq-deadline | sudo tee /sys/block/sdX/queue/scheduler
sudo grubby --update-kernel=ALL --args="scsi_mod.use_blk_mq=1 elevator=noop"
Choosing the Right Tool for the Job
- **`noop`**: Best for very fast devices like NVMe, SSDs behind smart hardware RAID controllers, or virtualized environments where the hypervisor already manages I/O. It’s essentially a FIFO queue, doing minimal reordering.
- **`mq-deadline`**: Often the default on modern kernels. It tries to prioritize read requests over writes to reduce latency for reads, and attempts to ensure fairness by setting deadlines. Good general-purpose scheduler for mixed workloads on both HDDs and some SSDs, especially where throughput is important.
- **`bfq` (Budget Fair Queuing)**: Optimized for desktop responsiveness and interactivity. It gives a specific ‘budget’ of I/O cycles to each process, ensuring low latency for interactive applications. If you’re running a database or a web server, this usually isn’t what you want; it can sacrifice overall throughput for local fairness.
Changing the scheduler on a running system via `sysfs` is temporary, good for testing. To make it persistent, you’ll want to add `elevator=<scheduler_name>` to your kernel boot parameters in `grub`. But listen, this isn’t a set-it-and-forget-it magic bullet. My opinion? Don’t blindly trust an internet forum or a benchmark from a decade ago. You absolutely have to benchmark your specific workload against different schedulers. What works for one database might choke another, or a file server. This bit me hard once when a supposedly ‘optimal’ `noop` setting caused inexplicable write stalls on a highly transactional system, turns out `mq-deadline` was better at dealing with the bursty writes. Observe `iostat -x` output, watch your application metrics, and be methodical.
The I/O scheduler is one of those deeper kernel tuning points that can subtly make or break performance, especially as systems scale and workloads get more complex. It’s not the first place you look, but when you’ve exhausted the obvious, knowing how to inspect and adjust this can save your bacon.
