Basics

What is a KVM VPS? KVM and NVMe explained, and how to verify what you got

KVM and NVMe explained for VPS buyers: a KVM hypervisor with reserved resources beside an NVMe disk with parallel command queues, plus commands that check the virtualization type and measure disk IOPS

When you shop for a VPS, two words show up on spec sheets more often than any others: KVM and NVMe. The first decides whether the resources you pay for are really yours or exist only on paper; the second decides how fast your database and website can breathe. The trouble is that printing those two words on a sales page costs the seller nothing. This article explains what a KVM VPS is, how NVMe differs from an ordinary SSD, why the disk's name gives nothing away, and which few commands tell you whether you received what you were promised.

What is a KVM VPS, and why does it matter to a buyer?

KVM stands for Kernel-based Virtual Machine: a virtualization module inside the Linux kernel itself that uses the processor's hardware features (Intel VT-x or AMD-V) to build "real" virtual machines. The word "real" carries technical weight here: every KVM server is a complete computer, with its own virtual CPU, dedicated RAM, disk and network card, and, most importantly, it boots its own kernel.

In practice, that means three things:

  • Dedicated RAM: 4 GB of RAM means 4 GB of RAM. It is reserved for you the moment the machine is created, not "up to 4 GB, as long as nobody else is using it".
  • An independent kernel: you can load kernel modules, which means WireGuard, Docker, special file systems and anything else that touches the kernel simply works, no excuses.
  • Any operating system: Ubuntu, Debian, Alma, even BSD or Windows. Because the hardware is virtual, the guest operating system has no restrictions.

And a bit of history: since February 2007 and version 2.6.20 of the Linux kernel, KVM has been part of the kernel itself, not an add-on layer installed alongside it.

Under the hood: the kernel, QEMU and virtio drivers

KVM handles only the hard part of the job: running the guest's instructions directly on the real processor and managing memory. Emulating the devices (the disk, the network card, the graphics card) is the job of a user-space program, usually QEMU.

If QEMU fully emulates an old IDE disk or an e1000 network card, every access to that device's registers pauses the virtual machine, and under load those pauses add up. The standard fix is virtio: paravirtualized devices whose guest driver knows it is virtual and, instead of imitating hardware, exchanges data with the host through a ring of shared memory. Checking takes one command:

lspci | grep -i virtio

00:03.0 Ethernet controller: Red Hat, Inc. Virtio network device
00:04.0 SCSI storage controller: Red Hat, Inc. Virtio block device

If instead of those two lines you see something like Intel Corporation 82540EM Gigabit Ethernet or an IDE controller, the server is running on emulated devices and gives up part of its performance. To confirm on the kernel side:

lsmod | grep virtio

virtio_net             57344  0
virtio_blk             20480  3
virtio_pci             28672  0
💡 A practical takeaway: "KVM" on a spec sheet only names the hypervisor, not how well it is configured. Two KVM servers with identical RAM and CPU can differ dramatically in performance because of the disk driver alone.

KVM vs OpenVZ, and the overselling problem

The second approach is container-based virtualization: OpenVZ and LXC. There is no virtual machine here at all; every "server" is a partition of one shared operating system and borrows the host's kernel. It is lighter and has less overhead, but you are the one who pays for that:

  • You can't choose the kernel: if the host runs an old kernel, so do you. Installing Docker on a cloud server or setting up a kernel-level VPN on an old OpenVZ host usually hits a wall.
  • Resources are "shared and borrowable": the RAM you see is often burst memory, not reserved memory.
  • Overselling becomes easy: because nothing is reserved, a seller can "sell", say, 200 GB of RAM on a host that has 64 GB, betting that not everyone will use it at the same time.

The classic signs of overselling are familiar: the server flies at noon and crawls at night, or free shows plenty of free RAM while processes get killed for lack of memory. On KVM this game is much harder to play, because each machine's RAM is set aside in advance. KVM vs OpenVZ in one sentence: one is a detached house with its own deed, the other is a room in the landlord's house.

A less-mentioned difference: inside a container, what free and top show may be the whole host's numbers rather than your share; on KVM the kernel is your own, so those numbers are your server's numbers. If you're torn between types of service, our comparison of VPS, dedicated and cloud servers draws the boundaries more precisely.

💡 Note: Even on KVM, the CPU is shared between machines, and that is normal. What KVM guarantees is reserved RAM and an independent kernel; a fair provider also keeps the CPU sharing ratio reasonable.

What is VPS steal time, and how does it expose CPU overselling?

No model guarantees reserved CPU, and Linux has a metric for exactly that: steal time, the st column. It is the percentage of time your virtual CPU had work ready to run but the hypervisor had given the physical core to another machine. It isn't idle time and it isn't waiting for the disk; it means your turn simply didn't come. On a physical server it is always zero.

vmstat 1 5

procs -----------memory---------- ---swap-- -----io---- -system-- -------cpu-------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0      0 612344  84120 1204880    0    0    41   126  384  702 11  3 85  1  1
 2  0      0 612344  84120 1204880    0    0     3    18  212  398  9  2 88  0  1
 1  0      0 611980  84120 1204884    0    0     0     0  198  361  7  1 91  0  1
 3  0      0 611704  84120 1204884    0    0     0    24  241  452 12  3 84  0  1
 1  0      0 611704  84120 1204884    0    0     0     8  205  377  8  2 89  0  1

The last number on each line is the steal time, with one reminder: the first line of vmstat is the average since boot, so read from the second line onwards. The rule of thumb: under 1% is normal, 1 to 5% is tolerable, and a sustained value above 10% means the host is crowded. The same number appears in top at the end of the %Cpu(s) line, labeled st, and mpstat -P ALL 1 breaks it down per core.

The key point: adding virtual cores doesn't cure steal time, and sometimes makes it worse, because a machine with more cores is harder for the host's scheduler to fit in. To record this number continuously, the tools in our Linux server monitoring guide make the job easy.

What is NVMe? NVMe vs SSD vs HDD at a glance

Now for the second word. A mechanical hard drive (HDD) has to move a physical head for every scattered read, which costs a few milliseconds per move. An SSD has no moving parts, but ordinary SSDs still speak SATA: an interface designed for mechanical drives, with a theoretical ceiling of 600 MB/s (about 550 in practice) and a single command queue. NVMe was written for flash from day one and sits directly on PCIe: tens of thousands of parallel queues and latency measured in microseconds.

The standards themselves put numbers on the difference: AHCI, the interface behind SATA, has one command queue holding at most 32 commands, whereas NVMe allows up to 65,535 queues with up to 65,536 commands in each. So when dozens of processes ask the disk for data at once, which is exactly what a busy web server does, SATA lines them all up in one narrow queue while NVMe genuinely works on them in parallel.

Disk typeRandom IOPS (4K)Typical latencyBandwidthCommand queues
HDD (7,200 rpm)about 75 to 805 to 10 msabout 160 MB/sone queue, 32 commands
SATA SSD50,000 to 100,000about 0.1 msup to 550 MB/sone queue, 32 commands
NVMe200,000 to over 1 million20 to 100 µsseveral GB/sup to 65,535 queues

What do these numbers mean for your site?

The real workload of a web server is small, scattered reads, which is exactly where the IOPS column matters most, not bandwidth. A WordPress page runs dozens of queries, and every query means a few small reads from disk. On an HDD each read takes several milliseconds, and together they swallow a large part of the response time; on NVMe the same reads are answered in microseconds, and what's left is PHP execution, not waiting for the disk. You feel the same effect in database imports, backups, apt upgrade and project builds.

The workload that shows the difference most brutally is writing with fsync: every time a database declares a transaction committed, it has to be sure the data has reached stable storage. On an HDD that means waiting for the head to move and the platter to spin; on NVMe it takes a few tens of microseconds. A back-of-the-envelope calculation says it all: a disk that completes 100 fsyncs per second keeps an import of 100,000 transactions waiting on the disk for nearly 17 minutes, while at 100 microseconds of latency the same job takes about 10 seconds.

Why is my disk called vda, not nvme0n1?

Inside a KVM virtual server, the output of lsblk usually looks like this:

lsblk -d -o NAME,ROTA,TYPE,SIZE,MODEL

NAME ROTA TYPE  SIZE MODEL
vda     0 disk   40G

The name vda means the device is presented through the virtio-blk driver, and the MODEL column is empty because virtio has no model to report. With virtio-scsi you'll see the name sda and the model QEMU HARDDISK. Either way, what you see is a virtual device, not the host's physical disk.

The consequence: not seeing nvme0n1 doesn't prove the underlying disk isn't NVMe. Conversely, seeing nvme0n1 guarantees nothing either, because a hypervisor can emulate an NVMe controller, and on the big cloud platforms network-attached disks are presented under the same name. The ROTA column is also just the hypervisor's claim: a zero means the guest kernel sees the disk as non-rotational, not that there is necessarily flash behind it.

⚠️ That is also why nvme smart-log, or reading disk health with smartctl, doesn't work inside an ordinary virtual server: the /dev/nvme0 path doesn't exist. Any guide that suggests it was written for a physical server.

How to check what you actually got

You don't have to trust the seller's brochure; a few commands are enough. First, log in to the server over SSH.

1) Virtualization type

systemd-detect-virt

kvm

If the output is kvm, you have a KVM server; openvz or lxc means a container, and none means a physical server. A second confirmation:

lscpu | grep -i -E 'hypervisor|virtualization'

Hypervisor vendor:      KVM
Virtualization type:    full

On a KVM server you should see Hypervisor vendor: KVM, and full means full virtualization. Two fallbacks for when systemd isn't available:

grep -o hypervisor /proc/cpuinfo | head -1
hypervisor

sudo dmidecode -s system-product-name
Standard PC (Q35 + ICH9, 2009)

2) Disk type

lsblk -d -o NAME,ROTA,TYPE,MODEL

The name nvme0n1 means the guest kernel sees an NVMe controller (whether passed through directly or emulated). A name of vda or sda with ROTA at zero means a non-rotational virtual disk: the most common case, and one that proves nothing about the hardware behind it. ROTA equal to one means the hypervisor presents the disk as rotational: walk away.

3) A real speed test with fio

apt install -y fio
fio --name=quicktest --filename=fio-test --size=256M --rw=randread --bs=4k --iodepth=32 --ioengine=libaio --direct=1 --runtime=15 --time_based --group_reporting
rm fio-test

Compare the IOPS figure in the output with the table above: a few hundred or fewer means a mechanical drive, a few tens of thousands means a SATA SSD, and anything above a hundred thousand means healthy NVMe. Cloud servers usually have a fair cap on each machine's IOPS so that one neighbor can't monopolize the disk; a steady, repeatable number matters more than a record.

Leave the --direct=1 option alone: it bypasses the Linux page cache, and without it you are measuring the speed of RAM, not the disk. On recent kernels, --ioengine=io_uring has less overhead.

⚠️ Run the test with randread and a small file, and delete the test file afterwards. Long, heavy write tests both eat into the flash's lifespan and slow down whatever service is running. The best time for this test is the first hour of a new server's life.

fio disk benchmark: how to read the output

fio's output is long, but only a few of its numbers matter for a decision:

quicktest: (groupid=0, jobs=1): err= 0: pid=2841
  read: IOPS=118k, BW=460MiB/s (482MB/s)(6899MiB/15001msec)
    slat (nsec): min=1500, max=98000, avg=2400.11
    clat (usec): min=45, max=2210, avg=268.55, stdev=91.30
     lat (usec): min=48, max=2213, avg=271.02, stdev=91.35
    clat percentiles (usec):
     |  1.00th=[  135], 50.00th=[  260], 95.00th=[  420],
     | 99.00th=[  545], 99.90th=[  865], 99.99th=[ 1418]

IOPS is the number of operations per second: here 118 thousand, which puts the disk in the NVMe class. clat is the completion latency of each operation, in microseconds. But the most important part is the percentiles line: the median is 260 microseconds, yet 99.99th says one request in ten thousand took 1,418 microseconds. Users don't feel the average; they feel the tail of the distribution.

One calculation helps you trust the output: average latency is roughly the queue depth divided by IOPS. 32 divided by 118,000 is about 271 microseconds, the same number as on the lat line. To measure pure latency, repeat the test with a queue depth of one:

fio --name=lat --filename=fio-test --size=256M --rw=randread --bs=4k \
    --iodepth=1 --ioengine=psync --direct=1 --runtime=15 --time_based
rm fio-test

An average clat below 200 microseconds is the sign of a healthy NVMe disk, around one millisecond smells like SATA, and several milliseconds means a mechanical drive or high-latency network storage. Repeat the test at two different times of day; a big difference between noon and midnight is the most telling result of all.

Slow server: is it the CPU, the RAM or the disk?

Before you switch servers, find the real bottleneck:

SymptomLikely causeCommand to check
The site slows down at certain hoursContention for CPU on the hostvmstat 1, watching the st column
CPU usage is low, yet everything is slowWaiting for disk I/OThe wa column in vmstat, and iostat -x 1
Processes get killed while RAM looks freeThe container's memory cap, or the OOM killerdmesg -T | grep -i oom
A database import takes foreverSlow writes with fsyncAn fio test with --rw=randwrite --fsync=1 --iodepth=1
IOPS halve at busy hoursA cap, or a heavy neighbor on the storageRepeat the same fio test at different hours
The network is fast but TTFB is highA bottleneck in PHP or a query, not the diskcurl -w '%{time_starttransfer}\n' -o /dev/null -s https://example.ir/

iostat is part of the sysstat package, and reading its output has a trap: the %util column only signals saturation on devices that serve requests one after another. On SSDs and NVMe drives, which have several parallel queues, this column can read 100% without the disk being anywhere near its limit, a caveat the iostat manual itself mentions. Better measures are the latency columns (r_await and w_await) and the queue length (aqu-sz).

Where NVMe works no miracles

NVMe only makes a noticeable difference when your bottleneck is the disk. There are three common situations where upgrading the disk changes nothing at all.

First, when the active data fits in RAM. Linux keeps everything it reads in the page cache; with a 2 GB database on an 8 GB server, almost every read is served from RAM, and the real bottleneck is the processor's single-core speed.

Second, when response time goes into processing, not reading. A page with thirty WordPress plugins and an unindexed query is slow even on the fastest disk in the world; the fix there is caching and repairing the query, the things covered in our guide to speeding up WordPress.

Third, when the problem is network distance. If the visitor is in Iran and the server is in Europe, every packet round trip costs tens of milliseconds and no disk can make up for it; what helps there is the server's location and a content delivery network. Measure first, then spend.

Buyer's checklist: ask these 7 questions before you pay

  1. Is the virtualization type stated explicitly? Look for the word "KVM" in the specs; "a powerful virtual server" with no technology named is a question mark.
  2. Is the RAM dedicated or burst? On KVM the default answer is "dedicated"; on OpenVZ, always ask.
  3. What exactly is the disk? If the listing only says "SSD", it is most likely SATA. NVMe gets named, because it is a competitive advantage.
  4. Is an IOPS cap published? Having a cap isn't bad; it is a sign of fair storage management. No number at all means no commitment at all.
  5. Can you test cheaply? That is the biggest advantage of hourly billing: at Mehran Host you can create a KVM server with an NVMe disk, run these same commands and, if the numbers don't satisfy you, delete the server. The whole experiment costs a few hours, not a month. Just be aware that powering the server off reduces the hourly rate but doesn't bring it to zero; the meter only stops when the server is deleted.
  6. Is the upgrade path clear? Ask how resources are increased and whether you can scale down later; on most platforms, shrinking a disk isn't possible.
  7. After delivery, check the seller's claims. systemd-detect-virt, lsblk and a fifteen-second fio run take less than two minutes altogether.

How does Mehran Host offer KVM and NVMe?

A Mehran Host cloud server is a KVM machine with an NVMe disk in an Iranian datacenter, billed by the hour from your wallet. Creating one is automatic: you choose the resources and the operating system, and the machine is usually delivered in under a minute with full root access.

In the customer panel, each server has several sections: an overview with live resource usage, power on/off and reboot, a web-based VNC console that works even when SSH is broken, Reinstall OS (with a typed confirmation), Upgrade for adding resources, and Backups. Two points matter when you buy: resources can only be increased, and decreasing them, the disk in particular, isn't possible; and backups are a separate add-on whose monthly price is charged by the hour, with a fixed cap on the number of versions kept.

Servers in Hetzner datacenters can also be ordered, paid for in Toman (Iran's everyday currency unit), and if your project doesn't need a server of its own, shared hosting on cPanel and DirectAdmin is simpler.

Now that you know what a KVM VPS is and what lies behind IOPS figures, no spec sheet will confuse you: KVM means real resources, NVMe means a disk that doesn't keep your database waiting, and fio is the tool that checks both claims in fifteen seconds. To put a provider to the test, create an hourly server and run these same commands; the hourly billing model is explained in our hourly cloud server guide.

Frequently asked questions

What is KVM virtualization, and how is it different from a container?

KVM, or Kernel-based Virtual Machine, is a module inside the Linux kernel that uses the processor's hardware features to build complete virtual machines; each machine boots its own independent kernel and gets reserved RAM. In container virtualization such as OpenVZ and LXC, all the servers share the host's kernel. As a result, only on KVM can you install any operating system and load kernel modules.

What is the difference between NVMe and an ordinary SSD?

The difference is the interface: both are flash storage with no moving parts, but an ordinary SSD talks over SATA, which was designed for mechanical drives, with one command queue of at most 32 commands and a ceiling of about 550 MB/s. NVMe sits directly on PCIe and allows up to 65,535 parallel queues, and for a web server handling dozens of small simultaneous requests, that parallelism matters more than bandwidth.

How can I tell whether my VPS is KVM or a container?

Run the systemd-detect-virt command on the server: an output of kvm means a full virtual machine, lxc or openvz means a container, and none means a physical server. For a second confirmation, look at the output of lscpu; on a KVM machine, the line Hypervisor vendor: KVM appears. Both commands finish in a few seconds.

Why doesn't the disk show up as nvme inside a virtual server?

Because the guest operating system sees a virtual device, not the host's physical disk. On most KVM servers the disk is presented through the virtio driver and named vda or sda, even when real NVMe sits behind it. So the device name proves or disproves nothing, and the only reliable test is measuring IOPS and latency with a tool such as fio; reading the disk's SMART data isn't possible inside such a server either.

What does high steal time mean, and what should I do about it?

Steal time is the percentage of time your virtual CPU had work ready but the hypervisor had given the physical core to another machine; you see it in the st column of vmstat 1. Under 1% is normal, and a sustained value above 10% means the host is crowded. Adding virtual cores won't fix it; measure for a few days and, if it persists, raise the issue with your provider.

Related tutorials

Ready for some hands-on practice?

A Mehran Host hourly cloud server is ready in under 60 seconds. Practice as much as you like and pay only for the hours you use. Estimate the cost with the pricing calculator before you sign up.