Kingsfordweg 151, 1043GR Amsterdam, The Netherlands ● 24/7 support — support@novogara.com
Knowledge base

IO scheduler and tuning

Modern kernels get this close to right on their own. There are a few settings worth checking, and a great many tuning guides worth ignoring.

Check what you have

cat /sys/block/nvme0n1/queue/scheduler

The one in brackets is active.

NVMe
none. The device has deep parallel queues of its own; a scheduler adds latency and reorders work that did not need reordering.
SAS and SATA SSD
mq-deadline. Low overhead, bounded latency.
Spinning disks
bfq if interactive responsiveness matters, mq-deadline for throughput.

Set it persistently with a udev rule rather than a command in rc.local, so it survives both a reboot and a disk replacement.

Readahead

blockdev --getra /dev/nvme0n1

The default suits general use. Raise it for large sequential reads — video delivery, backups, bulk analytics. Lower it for random access such as a database, where readahead fetches pages nobody wanted. See streaming and database basics.

Mount options worth setting

noatime — stop writing an access timestamp on every read. Almost nothing needs it and it turns reads into writes.

On ext4, data=ordered is the sensible default; do not move to writeback for a database unless you have thought hard about what a power cut does.

On XFS, the defaults are good. Resist the urge.

For SSDs and NVMe, discard matters: prefer a weekly fstrim.timer over the discard mount option, which issues trims inline and can cause latency spikes on some drives.

Writeback thresholds

By default Linux will buffer a large amount of dirty data before flushing it, which produces a stall when it finally does. On a machine with a great deal of memory and a write-heavy workload:

vm.dirty_ratio = 10
vm.dirty_background_ratio = 5

Smaller, more frequent flushes trade a little throughput for far smoother latency.

Measure, do not believe

Take a baseline with fio using your own access pattern, change one thing, measure again. See benchmarking a new server.

Watch iostat -x 2 while real traffic runs: %util near 100 with rising await means the device is the limit. If it is not, tuning the scheduler will not help — find the actual bottleneck with diagnosing a slow server first.

The honest summary

On good hardware with a current kernel, none on NVMe, noatime, a weekly trim and sensible dirty ratios is most of the available benefit. If your storage is slow after that, the answer is usually the workload or the hardware shape rather than a sysctl — and we would rather specify the right drives than have you tune around the wrong ones.


Still stuck? Mail support@novogara.com — an engineer answers, at any hour. Back to the knowledge base