Why Ordering Matters (for HDDs)
A spinning Hard Disk Drive (HDD) stores data on magnetic platters. To read or write data, a mechanical arm must physically move to the correct track — this movement is called a seek. A seek takes 5–15 milliseconds. That sounds small, but at 10,000 IOPS, seek time dominates everything.
If the disk receives requests for LBA 1, then LBA 10,000, then LBA 2, handling them in arrival order forces the arm to swing wildly across the platter. The I/O scheduler reorders these requests to minimize total arm movement — exactly like an elevator that services floors in one direction before reversing, rather than bouncing between floor 1 and floor 50 repeatedly.
Checking and Setting Your Scheduler
The active scheduler for a device is readable from /sys/block/<device>/queue/scheduler, shown in brackets alongside the other available options (e.g., [mq-deadline] kyber bfq none), and can be changed at runtime — no reboot required — by writing the desired scheduler's name to that same file.
Common Schedulers in Modern Linux
none (No-op): Does the minimum — merges adjacent requests and processes them FIFO. No reordering. Ideal for NVMe SSDs where seek time is zero and any reordering overhead is wasted CPU.
mq-deadline: Assigns a deadline to each request. Reads get a 500ms deadline; writes get a 5-second deadline. If a request is about to expire, it jumps the queue. Prevents starvation. Good default for SSDs in server workloads.
BFQ (Budget Fair Queueing): Treats I/O like a CPU scheduler — each process gets a "budget" of sectors. Prevents one process (a large rsync) from starving another (a web server). Excellent for desktop systems and HDDs. CPU-intensive; overkill for NVMe.
Kyber: Designed for fast, low-latency devices. Maintains separate queues for reads and synchronous writes, targeting specific latency goals. Simpler than BFQ, lower overhead.
The Multi-Queue Revolution
Modern storage devices (NVMe SSDs) have multiple hardware queues — an NVMe drive can have 64,000 queues, each with 64,000 entries. The old single-queue I/O scheduler was a bottleneck. Linux's blk-mq (multi-queue block layer) was introduced to match this parallelism, allowing each CPU core to submit I/O to its own queue without lock contention.
Interviewers frequently ask: "What I/O scheduler would you use for an NVMe SSD in a production database?" The correct answer is none or mq-deadline. The reasoning: NVMe has no seek penalty, so reordering provides no benefit. none has the lowest overhead. mq-deadline adds deadline-based starvation prevention, which is useful if multiple processes compete for the device. Saying "BFQ" for an NVMe database server is a red flag — it shows you know the scheduler names but not when to apply them.