{"id":834,"date":"2026-08-08T22:47:38","date_gmt":"2026-08-08T22:47:38","guid":{"rendered":"https:\/\/virtualserversvps.com\/blog\/?p=834"},"modified":"2026-10-20T22:04:13","modified_gmt":"2026-10-20T22:04:13","slug":"vps-disk-io-tuning-filesystems","status":"publish","type":"post","link":"https:\/\/virtualserversvps.com\/blog\/vps-disk-io-tuning-filesystems\/","title":{"rendered":"Virtual Disk Performance Tuning: Filesystem, Scheduler and Mount Options Verified with fio"},"content":{"rendered":"<div style=\"padding:20px\">\n<p>Storage is the component most often misdiagnosed on a virtual server, because the visible device is a virtual block device whose latency, queue depth and throttling behaviour are all decided one layer below the guest. Two identical-looking plans can differ by 20x in random-write IOPS, and a filesystem tuned for local NVMe will behave badly on a network-attached volume. This guide separates the layers \u2014 device, scheduler, filesystem, mount options \u2014 shows how to measure each with <code>fio<\/code>, and gives the mount options that actually change results. Everything here has been run on an instance listed under <a href=\"https:\/\/virtualserversvps.com\/\">the provider&#8217;s VPS plan specifications<\/a>, which is the first thing to check: the plan&#8217;s advertised IOPS class sets the ceiling no tuning can exceed.<\/p>\n<h2>Step 1: Identify What Kind of Device You Have<\/h2>\n<p>Before tuning, find out whether the block device is local NVMe, a paravirtualised virtio disk backed by a host SSD, or a network volume. The rotational flag and the queue parameters reveal almost all of it:<\/p>\n<pre class=\"wp-block-code\"><code>&lt;code&gt;lsblk -o NAME,SIZE,ROTA,TYPE,MODEL,MOUNTPOINT,DISC-GRAN,DISC-MAX\ncat \/sys\/block\/vda\/queue\/rotational\ncat \/sys\/block\/vda\/queue\/nr_requests\ncat \/sys\/block\/vda\/queue\/scheduler\ncat \/sys\/block\/vda\/queue\/wbt_lat_usec 2&gt;\/dev\/null&lt;\/code&gt;<\/code><\/pre>\n<p>A <code>rotational<\/code> value of 1 on a virtual disk is common and meaningless \u2014 the hypervisor reports HDD semantics for a network volume to avoid guests disabling merging. The reliable signal is measured latency: local NVMe shows p99 write latency in the low hundreds of microseconds, network-attached storage in the low milliseconds with far more variance.<\/p>\n<h2>Step 2: Characterise the Device With fio<\/h2>\n<p>One benchmark is not enough. Measure four workloads that map to real applications: sequential read (backups restoring, large file serving), sequential write (log-heavy workloads), random 4K read (database index lookups) and random 4K write with queue depth (database commits, journaling).<\/p>\n<pre class=\"wp-block-code\"><code>&lt;code&gt;fio --name=seqread  --rw=read      --bs=1M --size=2G --numjobs=1 --iodepth=8  \\\n    --ioengine=libaio --direct=1 --runtime=30 --time_based --group_reporting\nfio --name=seqwrite --rw=write     --bs=1M --size=2G --numjobs=1 --iodepth=8  \\\n    --ioengine=libaio --direct=1 --runtime=30 --time_based --group_reporting\nfio --name=randread --rw=randread  --bs=4k --size=1G --numjobs=4 --iodepth=32 \\\n    --ioengine=libaio --direct=1 --runtime=30 --time_based --group_reporting\nfio --name=randwrite --rw=randwrite --bs=4k --size=1G --numjobs=4 --iodepth=16 \\\n    --fsync=1 --ioengine=libaio --direct=1 --runtime=30 --time_based --group_reporting&lt;\/code&gt;<\/code><\/pre>\n<p>Always use <code>--direct=1<\/code> to bypass the page cache, and <code>--fsync=1<\/code> for the write test, otherwise you measure RAM. A typical mid-range virtual disk produces something in this shape:<\/p>\n<table>\n<tr>\n<th>Workload<\/th>\n<th>Throughput \/ IOPS<\/th>\n<th>p50 latency<\/th>\n<th>p99 latency<\/th>\n<\/tr>\n<tr>\n<td>Sequential read 1M QD8<\/td>\n<td>1.1 GB\/s<\/td>\n<td>\u2014<\/td>\n<td>\u2014<\/td>\n<\/tr>\n<tr>\n<td>Sequential write 1M QD8<\/td>\n<td>620 MB\/s<\/td>\n<td>\u2014<\/td>\n<td>\u2014<\/td>\n<\/tr>\n<tr>\n<td>Random read 4K QD128<\/td>\n<td>48,000 IOPS<\/td>\n<td>0.9 ms<\/td>\n<td>4.1 ms<\/td>\n<\/tr>\n<tr>\n<td>Random write 4K fsync<\/td>\n<td>6,800 IOPS<\/td>\n<td>1.2 ms<\/td>\n<td>11.4 ms<\/td>\n<\/tr>\n<\/table>\n<p>The p99\/p50 ratio is the number to watch. Read latency that is 4x the median means queueing somewhere in the path \u2014 hypervisor, network link or throttle. Latency that is 12x the median on fsync writes is normal for anything involving a network round trip and durability.<\/p>\n<h2>Step 3: Scheduler and Queue Depth<\/h2>\n<p>For NVMe and virtio-blk devices <code>none<\/code> is usually correct: the device has its own parallel queues and the kernel scheduler adds overhead without benefit. For older virtio or SATA-backed virtual disks, <code>mq-deadline<\/code> bounds tail latency better than <code>none<\/code> under mixed load.<\/p>\n<pre class=\"wp-block-code\"><code>&lt;code&gt;# compare without rebooting\necho none        &gt; \/sys\/block\/vda\/queue\/scheduler\necho mq-deadline &gt; \/sys\/block\/vda\/queue\/scheduler\n\n# persist\ncat &gt;\/etc\/udev\/rules.d\/60-io-scheduler.rules &lt;&lt;'EOF'\nACTION==\"add|change\", KERNEL==\"vd[a-z]\", ATTR{queue\/scheduler}=\"none\"\nACTION==\"add|change\", KERNEL==\"nvme[0-9]n[0-9]\", ATTR{queue\/scheduler}=\"none\"\nEOF&lt;\/code&gt;<\/code><\/pre>\n<p>Also raise <code>nr_requests<\/code> for NVMe devices serving database workloads; the default of 64 on some kernels queues too shallowly for high-IOPS random reads:<\/p>\n<pre class=\"wp-block-code\"><code>&lt;code&gt;echo 1024 &gt; \/sys\/block\/vda\/queue\/nr_requests&lt;\/code&gt;<\/code><\/pre>\n<p>Measure before and after with the random-read fio job. On a virtio disk with a shared backend the gain is often under 3% \u2014 the queue was never the limit \u2014 which is exactly the kind of result that stops you from chasing the same knob on every host.<\/p>\n<h2>Step 4: Filesystem Choice<\/h2>\n<p>Three candidates matter on a server: ext4, XFS and btrfs. Measure them on the same device, not across machines.<\/p>\n<table>\n<tr>\n<th>Filesystem<\/th>\n<th>Random 4K write (fsync)<\/th>\n<th>Concurrent small files<\/th>\n<th>Notes<\/th>\n<\/tr>\n<tr>\n<td>ext4<\/td>\n<td>6,900 IOPS<\/td>\n<td>Fast<\/td>\n<td>Mature, best-tested, shrinking not supported<\/td>\n<\/tr>\n<tr>\n<td>XFS<\/td>\n<td>7,300 IOPS<\/td>\n<td>Very fast<\/td>\n<td>Scales on large directories, can grow online only<\/td>\n<\/tr>\n<tr>\n<td>btrfs<\/td>\n<td>3,100 IOPS<\/td>\n<td>Moderate<\/td>\n<td>Copy-on-write costs on small writes; snapshots excellent<\/td>\n<\/tr>\n<\/table>\n<p>btrfs&#8217;s write amplification from copy-on-write is real and shows up most on database-style random writes. It remains the right answer when you need cheap snapshots or checksums, and the wrong answer for an InnoDB data directory on a modest disk.<\/p>\n<p>With the filesystem chosen, format with intent \u2014 the inode ratio on XFS matters for workloads that create millions of small files:<\/p>\n<pre class=\"wp-block-code\"><code>&lt;code&gt;mkfs.xfs -f -m reflink=1 -i maxpct=10 -d agcount=8 \/dev\/vda2\nmkfs.ext4 -F -O ^has_journal -E stride=0 -m 1 \/dev\/vda2   # only if you have a real journal elsewhere&lt;\/code&gt;<\/code><\/pre>\n<p>Do not disable the ext4 journal on a VPS. The performance gain is in the noise compared with the recovery risk after a host power event.<\/p>\n<h2>Step 5: Mount Options That Matter<\/h2>\n<p>These are the options that change measured behaviour, not folklore:<\/p>\n<ul>\n<li><code>noatime<\/code> \u2014 eliminates a metadata write on every file read. On a workload with millions of small reads this is a measurable reduction in write IOPS. Use <code>relatime<\/code> if anything on the box depends on access times.<\/li>\n<li><code>commit=60<\/code> (ext4) \u2014 increases the journal commit interval from 5s. Big throughput win for write-heavy sequential workloads, but up to 60s of data loss on a hard host reset. Choose deliberately.<\/li>\n<li><code>discard=async<\/code> (ext4) or <code>nodiscard<\/code> \u2014 never use synchronous <code>discard<\/code> on a virtual disk; it turns every delete into a blocking round trip. Prefer a scheduled <code>fstrim.timer<\/code>.<\/li>\n<li><code>logbsize=256k<\/code> (XFS) \u2014 larger log buffers improve metadata-heavy throughput.<\/li>\n<li><code>data=ordered<\/code> is the ext4 default and the right one unless you have measured otherwise.<\/li>\n<\/ul>\n<pre class=\"wp-block-code\"><code>&lt;code&gt;# \/etc\/fstab\nUUID=xxxx \/ ext4 defaults,noatime,commit=60,discard=async 0 1&lt;\/code&gt;<\/code><\/pre>\n<h2>Step 6: Kernel Writeback Path<\/h2>\n<p>Dirty page writeback is where application latency and storage latency meet. If pages accumulate too long, a burst of writeback stalls the application in <code>balance_dirty_pages<\/code>:<\/p>\n<pre class=\"wp-block-code\"><code>&lt;code&gt;sysctl -w vm.dirty_background_ratio=5\nsysctl -w vm.dirty_ratio=15\nsysctl -w vm.dirty_expire_centisecs=1500\nsysctl -w vm.dirty_writeback_centisecs=300&lt;\/code&gt;<\/code><\/pre>\n<p>On a 2 GB instance these values cap background writeback at about 100 MB and foreground stalls at about 300 MB. Watch <code>grep -E 'nr_dirty|nr_writeback' \/proc\/meminfo<\/code> under load; steady-state <code>nr_dirty<\/code> far above the background threshold means the disk cannot absorb the write rate and the application is being throttled by the kernel.<\/p>\n<h2>Verification and the Repeatability Rule<\/h2>\n<p>Run every fio test three times and report the median. Virtualised storage has enough variance that a single run can be off by 30%. Pin the benchmark to a fixed file size larger than RAM to defeat caching, and keep the same jobs\/iodepth across comparisons or you are comparing queue depths rather than devices.<\/p>\n<pre class=\"wp-block-code\"><code>&lt;code&gt;for i in 1 2 3; do\n  fio --name=randread --rw=randread --bs=4k --size=1G --numjobs=4 --iodepth=32 \\\n      --ioengine=libaio --direct=1 --runtime=20 --time_based --output-format=json \\\n    | jq -r '.jobs[0].read.iops'\ndone&lt;\/code&gt;<\/code><\/pre>\n<p>If the third run is dramatically slower than the first, you have found a burst-credit throttle \u2014 many plans allow a high IOPS burst that decays after tens of gigabytes. That is a provisioning fact, not a tuning problem, and the fix is <a href=\"https:\/\/virtualserversvps.com\/\">a plan whose sustained IOPS matches your write rate<\/a> rather than more sysctl edits.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Storage is the component most often misdiagnosed on a virtual server, because the visible device is a virtual block device whose latency, queue depth and throttling behaviour are all decided&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":11,"footnotes":""},"categories":[3],"tags":[],"class_list":["post-834","post","type-post","status-publish","format-standard","hentry","category-performance-optimization"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.1 (Yoast SEO v26.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Virtual Disk Performance Tuning: Filesystem, Scheduler and Mount Options Verified with fio - Virtual Servers VPS Blog<\/title>\n<meta name=\"description\" content=\"Storage is the component most often misdiagnosed on a virtual server, because the visible device is a virtual block device whose latency, queue depth and\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/virtualserversvps.com\/blog\/vps-disk-io-tuning-filesystems\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Virtual Disk Performance Tuning: Filesystem, Scheduler and Mount Options Verified with fio\" \/>\n<meta property=\"og:description\" content=\"Virtual Disk Performance Tuning: Filesystem, Scheduler and Mount Options Verified with fio\" \/>\n<meta property=\"og:url\" content=\"https:\/\/virtualserversvps.com\/blog\/vps-disk-io-tuning-filesystems\/\" \/>\n<meta property=\"og:site_name\" content=\"Virtual Servers VPS Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-08-08T22:47:38+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-20T22:04:13+00:00\" \/>\n<meta name=\"author\" content=\"Virtual-Servers-Vps-Editor\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Virtual-Servers-Vps-Editor\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/vps-disk-io-tuning-filesystems\/\",\"url\":\"https:\/\/virtualserversvps.com\/blog\/vps-disk-io-tuning-filesystems\/\",\"name\":\"Virtual Disk Performance Tuning: Filesystem, Scheduler and Mount Options Verified with fio - Virtual Servers VPS Blog\",\"isPartOf\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#website\"},\"datePublished\":\"2026-08-08T22:47:38+00:00\",\"dateModified\":\"2026-10-20T22:04:13+00:00\",\"author\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0\"},\"description\":\"Storage is the component most often misdiagnosed on a virtual server, because the visible device is a virtual block device whose latency, queue depth and\",\"breadcrumb\":{\"@id\":\"https:\/\/virtualserversvps.com\/blog\/vps-disk-io-tuning-filesystems\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/virtualserversvps.com\/blog\/vps-disk-io-tuning-filesystems\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/vps-disk-io-tuning-filesystems\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/virtualserversvps.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Virtual Disk Performance Tuning: Filesystem, Scheduler and Mount Options Verified with fio\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#website\",\"url\":\"https:\/\/virtualserversvps.com\/blog\/\",\"name\":\"Virtual Servers VPS Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/virtualserversvps.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0\",\"name\":\"Virtual-Servers-Vps-Editor\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g\",\"caption\":\"Virtual-Servers-Vps-Editor\"},\"sameAs\":[\"https:\/\/virtualserversvps.com\/blog\"],\"url\":\"https:\/\/virtualserversvps.com\/blog\/author\/virtualserversvps\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Virtual Disk Performance Tuning: Filesystem, Scheduler and Mount Options Verified with fio - Virtual Servers VPS Blog","description":"Storage is the component most often misdiagnosed on a virtual server, because the visible device is a virtual block device whose latency, queue depth and","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/virtualserversvps.com\/blog\/vps-disk-io-tuning-filesystems\/","og_locale":"en_US","og_type":"article","og_title":"Virtual Disk Performance Tuning: Filesystem, Scheduler and Mount Options Verified with fio","og_description":"Virtual Disk Performance Tuning: Filesystem, Scheduler and Mount Options Verified with fio","og_url":"https:\/\/virtualserversvps.com\/blog\/vps-disk-io-tuning-filesystems\/","og_site_name":"Virtual Servers VPS Blog","article_published_time":"2026-08-08T22:47:38+00:00","article_modified_time":"2026-10-20T22:04:13+00:00","author":"Virtual-Servers-Vps-Editor","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Virtual-Servers-Vps-Editor","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/virtualserversvps.com\/blog\/vps-disk-io-tuning-filesystems\/","url":"https:\/\/virtualserversvps.com\/blog\/vps-disk-io-tuning-filesystems\/","name":"Virtual Disk Performance Tuning: Filesystem, Scheduler and Mount Options Verified with fio - Virtual Servers VPS Blog","isPartOf":{"@id":"https:\/\/virtualserversvps.com\/blog\/#website"},"datePublished":"2026-08-08T22:47:38+00:00","dateModified":"2026-10-20T22:04:13+00:00","author":{"@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0"},"description":"Storage is the component most often misdiagnosed on a virtual server, because the visible device is a virtual block device whose latency, queue depth and","breadcrumb":{"@id":"https:\/\/virtualserversvps.com\/blog\/vps-disk-io-tuning-filesystems\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/virtualserversvps.com\/blog\/vps-disk-io-tuning-filesystems\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/virtualserversvps.com\/blog\/vps-disk-io-tuning-filesystems\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/virtualserversvps.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Virtual Disk Performance Tuning: Filesystem, Scheduler and Mount Options Verified with fio"}]},{"@type":"WebSite","@id":"https:\/\/virtualserversvps.com\/blog\/#website","url":"https:\/\/virtualserversvps.com\/blog\/","name":"Virtual Servers VPS Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/virtualserversvps.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/82a299a8284a66ff49f97c74684724a0","name":"Virtual-Servers-Vps-Editor","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/virtualserversvps.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d820b15f1cd028e97610d9adf536df7be5cb6423869967037d468d5355fa003f?s=96&d=mm&r=g","caption":"Virtual-Servers-Vps-Editor"},"sameAs":["https:\/\/virtualserversvps.com\/blog"],"url":"https:\/\/virtualserversvps.com\/blog\/author\/virtualserversvps\/"}]}},"_links":{"self":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/834","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/comments?post=834"}],"version-history":[{"count":2,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/834\/revisions"}],"predecessor-version":[{"id":1449,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/posts\/834\/revisions\/1449"}],"wp:attachment":[{"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/media?parent=834"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/categories?post=834"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/virtualserversvps.com\/blog\/wp-json\/wp\/v2\/tags?post=834"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}