Skip to content
Back to Blog
Performance11 min read

Advanced NVMe VPS Hosting: 7 Providers with Real SSD Upgrades

Deep-dive performance tuning, I/O benchmarks, and latency optimization for NVMe VPS deployments—beyond marketing claims.

Written by Abdul AbrorTechnical Hosting Support Engineer
Advanced NVMe VPS Hosting: 7 Providers with Real SSD Upgrades
On this page

Most VPS providers slap "NVMe" in their marketing copy and call it a day. Real NVMe performance depends on queue depth tuning, I/O scheduler choices, filesystem alignment, and whether the hypervisor exposes virtio-blk or virtio-scsi. This guide skips the sales pitch and focuses on what actually matters when you're running high-throughput databases, real-time analytics, or latency-sensitive applications on NVMe-backed virtual machines.

Understanding NVMe over-provisioning in virtualized environments

NVMe drives in bare-metal servers deliver sub-100 microsecond latency and millions of IOPS. Virtualization adds layers. The hypervisor's storage stack, the virtio driver model, and the QEMU block layer all introduce overhead. Some providers use thick provisioning with dedicated NVMe namespaces per VM; others use thin provisioning with shared LVM volumes or Ceph RBD backed by NVMe pools.

Check your actual device type first:

lsblk -d -o NAME,ROTA,DISC-GRAN

ROTA=0 means non-rotational (SSD or NVMe). DISC-GRAN shows discard granularity—zero means TRIM isn't exposed, which happens with some virtualized setups. If you see /dev/vda instead of /dev/nvme0n1, you're using virtio-blk. That's fine for most workloads but limits queue depth compared to virtio-scsi or direct NVMe passthrough.

I/O scheduler tuning for NVMe block devices

The default I/O scheduler on modern kernels is mq-deadline or none for NVMe devices. Check what's active:

cat /sys/block/vda/queue/scheduler

For NVMe-backed VPS instances, none often performs best because NVMe controllers handle command reordering internally. The kernel scheduler just adds latency. Switch to none if you're running databases or key-value stores:

echo none > /sys/block/vda/queue/scheduler

Make it persistent by adding a udev rule in /etc/udev/rules.d/60-scheduler.rules:

ACTION=="add|change", KERNEL=="vd[a-z]", ATTR{queue/scheduler}="none"

If your workload is mixed (batch writes and latency-sensitive reads), mq-deadline with a lower write_expire setting can help. I've tuned this for WordPress caching layers that need predictable read latency during backup windows.

Queue depth and virtio driver optimization

NVMe devices support thousands of queue pairs. Virtio-blk in KVM typically exposes one queue per vCPU. Check current queue depth:

cat /sys/block/vda/queue/nr_requests

Default is often 256. For write-heavy workloads (log ingestion, time-series databases), increase it:

echo 1024 > /sys/block/vda/queue/nr_requests

Watch out for memory pressure. Larger queue depths consume more kernel memory for tracking I/O requests. On VPS instances with 2-4 GB RAM, keep it under 512.

Virtio multiqueue can parallelize I/O across vCPUs. Verify it's enabled by checking the number of IRQs for your block device:

grep vda /proc/interrupts | wc -l

If you see only one or two lines, multiqueue isn't active. Some providers disable it to reduce hypervisor overhead. You can't fix this from the guest, but you can ask support if virtio-blk-mq is available.

Filesystem alignment and block size tuning

NVMe devices perform best when I/O is aligned to their physical sector size and erase block boundaries. Most consumer NVMe drives use 4K sectors; datacenter models sometimes use 8K or 16K. Check your device geometry:

blockdev --getpbsz /dev/vda
blockdev --getiomin /dev/vda
blockdev --getioopt /dev/vda

IOMIN is the minimum I/O size; IOOPT is the preferred size for performance. XFS and ext4 handle alignment automatically if you format with correct stripe geometry. For XFS on NVMe:

mkfs.xfs -f -d su=4k,sw=1 /dev/vda1

The su (stripe unit) should match your physical sector size. sw (stripe width) is 1 for single devices. If you're using LVM or software RAID, adjust sw to match the number of data devices.

Ext4 users should set stride and stripe-width during format:

mkfs.ext4 -E stride=1,stripe_width=1 /dev/vda1

Calculate stride as (chunk size / block size). For 4K chunks and 4K blocks, stride=1. These parameters affect how the allocator places data and can reduce fragmentation under heavy write workloads.

Mount options that actually matter

I see a lot of cargo-cult mount options copied from decade-old blog posts. For NVMe-backed VPS storage, focus on these:

  • noatime or relatime: Skip access time updates. Noatime is faster; relatime is a safer default that still updates atime when the file is modified.
  • discard or nodiscard: TRIM support. Use discard=async on kernels 5.6+ for batched TRIM operations with lower overhead.
  • barrier=0 / nobarrier: Don't use these. They disable write barriers and risk data corruption on crashes. NVMe drives are fast enough that barrier overhead is negligible.

XFS example:

mount -o noatime,discard=async /dev/vda1 /mnt/data

Add it to /etc/fstab:

/dev/vda1  /mnt/data  xfs  noatime,discard=async  0  2

Benchmarking actual NVMe performance

Marketing specs are useless. Run your own tests with fio to measure sequential throughput, random IOPS, and latency distribution.

Install fio:

apt install fio  # Debian/Ubuntu
yum install fio  # RHEL/CentOS

Random 4K read test (simulates database workload):

fio --name=randread --ioengine=libaio --iodepth=32 --rw=randread --bs=4k --direct=1 --size=1G --numjobs=4 --runtime=60 --group_reporting

Key metrics: IOPS and clat (completion latency). Good NVMe-backed VPS instances hit 20K+ IOPS on random reads with sub-millisecond p99 latency. Anything under 10K IOPS suggests the storage backend is either SATA SSD or oversubscribed.

Sequential write test:

fio --name=seqwrite --ioengine=libaio --iodepth=16 --rw=write --bs=1M --direct=1 --size=2G --numjobs=1 --runtime=60 --group_reporting

Expect 500 MB/s or higher on properly configured NVMe. If you're seeing 200-300 MB/s, the hypervisor is throttling or you're on SATA.

Latency percentiles matter more than average IOPS

Average IOPS look great in dashboards. P99 latency is what kills application performance. Run the same random read test and check the latency distribution at the bottom of fio output:

clat percentiles (usec):
 |  1.00th=[  220],  5.00th=[  245], 10.00th=[  265],
 | 50.00th=[  330], 90.00th=[  420], 95.00th=[  465],
 | 99.00th=[  570], 99.50th=[  635], 99.90th=[  775]

If p99 jumps above 2-3 milliseconds, your "NVMe" VPS is probably backed by network storage or the noisy neighbor effect is severe. I've seen providers advertise NVMe while running guests on Ceph clusters with spinning disks in the lower tiers.

What to look for in provider claims

Most VPS providers advertising NVMe fall into three buckets:

  1. True local NVMe: Physical NVMe drives in the hypervisor host, exposed as virtio-blk or virtio-scsi. Best performance, lowest latency, but no live migration without downtime.
  2. NVMe-backed distributed storage: Ceph or similar with NVMe OSDs. Good performance if the network is fast (25G+ interconnects), but adds latency and depends on cluster health.
  3. Marketing NVMe: SATA SSDs in the backend with "NVMe-like performance" claims. Run benchmarks.

Ask support these questions:

  • Is the storage local or network-attached?
  • What's the actual device model (even if virtualized)?
  • Is TRIM/discard supported and passed through to the guest?
  • What's the typical noisy neighbor isolation (IOPS limits, bandwidth throttling)?

Evaluating real providers

Without citing specific pricing or performance numbers, seven classes of providers consistently deliver on NVMe claims:

  1. Bare-metal-focused hosts that also offer VPS often use local NVMe with minimal virtualization overhead.
  2. Cloud providers with dedicated instance types ("storage-optimized" tiers) usually provision local NVMe.
  3. Smaller regional providers targeting high-performance workloads sometimes offer better price-to-performance than big names.
  4. Managed hosting providers that specialize in databases or real-time apps tend to use true local NVMe for their VPS tiers.
  5. Self-service cloud platforms with granular instance configuration let you choose NVMe explicitly.
  6. Providers that publish actual fio benchmark results in their documentation tend to be more transparent about backend storage.
  7. VPS hosts that offer custom kernel parameters or direct device passthrough are usually confident in their hardware.

Test before committing. Spin up the smallest instance, run fio for an hour, and check if throttling kicks in. Some providers allow burst IOPS for the first few minutes, then clamp down hard.

How does over-provisioning affect your workload?

NVMe drives lose performance as they fill up. Consumer drives drop from 3000 MB/s to 500 MB/s when 80% full because the SLC cache exhausts and writes hit slower TLC/QLC cells. Datacenter NVMe drives have better over-provisioning (extra hidden capacity), but virtualized environments add another layer.

Keep guest filesystems under 70% full for sustained write performance. Monitor disk usage:

df -h /

If you're running databases, leave 20-30% free space for the allocator to avoid fragmentation. XFS especially benefits from free space for efficient allocation group balancing.

Check your actual used vs free TRIM blocks:

fstrim -v /

If it returns "0 B trimmed", TRIM isn't working. Either the provider doesn't support it or you didn't mount with discard. Periodic fstrim via cron is a fallback:

0 2 * * 0 /sbin/fstrim / >> /var/log/fstrim.log 2>&1

Tuning for specific workloads

High-write databases (PostgreSQL, MySQL)

Increase kernel dirty page thresholds to batch writes:

sysctl -w vm.dirty_ratio=40
sysctl -w vm.dirty_background_ratio=10

PostgreSQL benefits from setting wal_sync_method=fdatasync and synchronous_commit=off for non-critical data. MySQL InnoDB should use innodb_flush_method=O_DIRECT to bypass page cache.

Time-series and log ingestion

Use XFS with logbsize=256k to reduce metadata transaction overhead:

mkfs.xfs -f -l logbsize=256k /dev/vda1

Disable atime entirely and use larger I/O sizes in your application config. InfluxDB, Prometheus, and similar workloads often see 30-40% write throughput gains with proper block alignment.

Content delivery and caching

For Varnish, Redis, or Nginx caching layers, focus on read latency. Use mq-deadline scheduler with short read_expire:

echo mq-deadline > /sys/block/vda/queue/scheduler
echo 100 > /sys/block/vda/queue/iosched/read_expire

Enable read-ahead for large file serving:

blockdev --setra 2048 /dev/vda

That's 1 MB of read-ahead (2048 * 512-byte sectors).

When does NVMe not matter?

If your VPS workload is CPU-bound (web app servers behind a load balancer, stateless microservices), NVMe won't help much. Measure your actual I/O wait time:

vmstat 1 10

If the wa (I/O wait) column stays under 5%, you're not storage-bottlenecked. Save money and pick slower SSD tiers.

Similarly, if you're using network file systems (NFS, GlusterFS) for shared storage, the NVMe backing your root disk is irrelevant. The network becomes the bottleneck at around 1-2 GB/s even on 10G links.

FAQ

How do I verify my VPS actually has NVMe and not SATA SSD?
Run lsblk -d -o NAME,ROTA,PHY-SEC and fio random read tests. Real NVMe hits 20K+ IOPS at sub-millisecond p99 latency. SATA SSD tops out around 10-15K IOPS with higher latency. Also check dmesg | grep -i nvme right after boot—though virtualized devices won't always report the underlying hardware.

Does the I/O scheduler matter if the provider throttles IOPS?
Yes, but less. Throttling happens at the hypervisor level after the scheduler makes decisions. Using none or mq-deadline still affects how requests are submitted to the virtio layer, which can reduce guest CPU overhead even if total IOPS is capped.

Should I use discard=async or run fstrim manually?
Both work. discard=async on kernel 5.6+ is lower overhead because TRIM operations are batched. Older kernels block on every discard, which can stall I/O. Manual fstrim via weekly cron is safer on older systems but means temporary performance loss as space is reclaimed in bursts.

Can I pass through a physical NVMe device to a VPS guest?
Some providers offer dedicated servers with KVM where you can do PCIe passthrough, but that's not typical VPS. If you need true bare-metal NVMe performance, look for dedicated or hybrid offerings.

Why does my fio benchmark show great IOPS but my database is still slow?
Check fsync behavior. Databases call fsync after every transaction by default, which forces data to persistent storage. That bypasses most caching and hits the actual device latency. Run fio with --fsync=1 to simulate database workload:

fio --name=dbsim --ioengine=libaio --iodepth=1 --rw=randwrite --bs=16k --direct=1 --fsync=1 --size=1G --runtime=60

If IOPS drop below 1000, your storage can't handle synchronous writes well.

What to check first when performance drops

Start with iostat to confirm the block device is the bottleneck:

iostat -x 2

Watch %util and await. If %util is near 100% and await (average wait time) is climbing, you're saturated. Check if a runaway process is doing heavy I/O:

iotop -o

Look for queue depth saturation:

cat /sys/block/vda/inflight

If both numbers (reads and writes in flight) are consistently high, your application is submitting more I/O than the device can handle. Either optimize the app, increase queue depth, or move to a higher-tier instance.

Finally, check the provider's status page. Shared storage backends fail. Hypervisor hosts have hardware issues. Noisy neighbors spike. If none of your tuning helps, open a ticket with your fio results and ask if there's a known issue on the host node.