Two VPS plans can advertise “2 vCPU / 4 GB / NVMe” and deliver 4x different throughput under load. The number on the order page is a ceiling, not a guarantee. This article works through what the ceiling actually means — the scheduler weights, the overcommit ratio, and the I/O throttle — and shows you how to measure your real allocation in about ten minutes.
CPU: Shares Are Weights, Not Cores
KVM guests run as Linux threads on the host, scheduled by CFS (Completely Fair Scheduler). A guest with 2 vCPU is two host threads with a `cpu.shares` weight. The default weight per core is 1024. A provider that sets your two cores to shares=2048 while a neighbour runs eight cores at shares=8192 is telling the scheduler to give you 1/5 of the contention window when both are runnable. On an idle host you get the full two cores; on a busy host you get your weight ratio.
| Allocation model | Contract | Typical steal under load | Best for |
|---|---|---|---|
| Shared / overcommitted | cpu.shares weight only | 3–15% | bursty web traffic, dev boxes |
| Fair-share cgroup cap | `cpu.max` quota (e.g. 200000/100000) | < 2% of quota | steady web apps |
| Dedicated vCPU pinning | `cpuset` — exclusive physical cores | 0–0.5% | databases, latency-sensitive APIs |
Verify what you got. Steal time near zero plus a load average that tracks real work means you are effectively exclusive. Sustained steal above 4% under your own saturated load means you are sharing.
# Is your vCPU actually available? Saturate and watch steal for 30s.
sudo apt install -y sysstat
for i in $(seq 1 $(nproc)); do (yes > /dev/null &) ; done
vmstat 1 30 | awk 'NR==1||NR>2{print}'
pkill yes
# Interpretation: r column >> nproc is fine; st column = steal, that is the number to watch.
Memory: The Overcommit Ratio Decides Your Swap Rate
`MemTotal` inside the guest is never the story. The story is `vm.overcommit_ratio` and whether the host uses KSM and swap-backed guest memory. On a 1:1.5 host you will essentially never swap. On a 1:3 host, the hypervisor can balloon your guest and you will see swap activity that your own `swappiness` setting did not cause. Detect it before it becomes an incident:
# Inside the guest — page faults and swap-in from host pressure
grep -E 'pgmajfault|pswpin|pswpout' /proc/vmstat
# Watch major faults per second; a steady non-zero rate at idle load = host memory pressure
while :; do grep -E 'pgmajfault' /proc/vmstat; sleep 5; done
A useful rule for a 1 GB–4 GB instance: keep your application working set at or below 70% of `MemTotal`, and keep swap at 1–2 GB on NVMe. That leaves 30% as page cache headroom, which is where most of your read performance lives.
Storage: IOPS Throttling Is Invisible Until It Bites
Cloud providers enforce disk throughput with a token bucket, usually in the hypervisor’s blkio cgroup. You will not see it in `IOPS` on the invoice — you see it as latency spikes at consistent intervals. The tell-tale: latency that is flat at low queue depth and then jumps to tens of milliseconds at the exact same point every time.
# Locate your throttle ceiling with fio at increasing queue depth
for qd in 1 4 16 32 64; do
echo "--- QD $qd ---"
fio --name=vm --filename=/tmp/fio.tmp --size=1G --bs=4k --rw=randread \
--iodepth=$qd --ioengine=libaio --direct=1 --runtime=20 --time_based \
--group_reporting 2>/dev/null | grep -E 'iops=|lat \(usec\)'
done
rm -f /tmp/fio.tmp
Plot IOPS against queue depth. A healthy NVMe disappears into the ether until ~64 QD. A throttled plan goes flat at, say, 3000 IOPS while latency doubles at each step — that is your token bucket, and no amount of application tuning will move it.
What to Do With the Numbers
- If steal is high and IOPS are capped, the fix is a plan upgrade, not `sysctl`.
- If steal is low, IOPS climb cleanly, and RAM overcommit is benign — your host is honest, and every tuning guide on the internet applies directly.
- If RAM overcommit is the problem but CPU and I/O are clean, drop to a smaller application footprint: fewer PHP-FPM workers, smaller `shared_buffers`, no sidecar services you do not need.
How Providers Enforce I/O Without Saying So
Disk throughput limits are applied at the hypervisor, usually through QEMU’s throttling (`blkio` cgroups) or a storage-side token bucket. Both look identical from inside the guest, and both produce a characteristic signature: throughput that is perfectly flat regardless of how much concurrency you throw at it, and latency that grows linearly with queue depth because requests are queued behind the throttle rather than executed. The giveaway is `%util` in `iostat` sitting at 100% while the drive is clearly not saturated.
# Throttle signature: util pinned at 100%, high await, low throughput
iostat -x 2 10 | grep -A1 Device
# Device r/s rkB/s await %util
# nvme0n1 780 3152 42.8 100.0 <- 780 IOPS and 42ms await == token bucket
#
# Compare against your plan's advertised IOPS. If measured ~= advertised, you are capped.
sudo smartctl -a /dev/nvme0n1 2>/dev/null | grep -E 'Model|Firmware' # often virtualised anyway
Burst credits make this harder to read. Many plans allow short bursts above the sustained cap, so a 10-second fio run looks excellent while a 5-minute run collapses. Always test for at least 60 seconds when you are probing for throttling; short benchmarks measure the credit tank, not the throughput ceiling.
The Diagnostic Order for Any VPS Slowdown
- Measure steal first — it is the only metric you cannot fix from inside the guest.
- Measure I/O latency at fixed queue depth before you measure throughput; latency reveals throttling that throughput hides behind bursts.
- Measure available memory and swap-in rate; host overcommit shows up here, not in your own `swappiness`.
- Only after those three are clean does application tuning (PHP-FPM, buffer pools, worker counts) have any chance of helping.
The measured versions of these tables live in our published VPS benchmark dataset — CPU steal deltas, fio curves, and RAM overcommit behaviour per provider. Use the provider breakdown on the same site to pick an allocation model that matches your workload before you migrate.
If you are tuning a small VPS and want hardware that does not fight you, our VPS provider performance tables break down CPU steal, NVMe IOPS, and RAM overcommit behaviour across the hosts we test on. Newer KVM nodes with dedicated vCPU pinning make the numbers in this article reproducible rather than aspirational. Two hosts we keep coming back to: InterServer VPS for flat-rate pricing with no RAM upcharge, and Cloudways managed cloud if you would rather not manage the kernel yourself. Compare the two against the benchmark methodology we publish before you commit.


Leave a Reply
You must be logged in to post a comment.