VDS vs VPS by Workload Type: Choosing CPU Isolation for Databases vs Web Servers

VDS and VPS instances are usually compared with a single number: CPU steal. But steal only matters in proportion to what your server actually does. A static web server idling at 4% CPU will never notice a noisy neighbor. A PostgreSQL instance pushing 800 transactions per second feels every stolen cycle as rising p99 latency. This guide separates the VDS-versus-VPS decision by workload type, so you buy isolation where it pays and skip it where it does not.

How the Hypervisor Maps Your vCPUs

Both products hand you a virtual machine. The difference is scheduling. On an overcommitted VPS, a 16-core host may sell 32 or 48 vCPUs, betting that tenants do not peak simultaneously. Your vCPU is a time-slice on a physical core that others also use. On a VDS, physical cores are pinned to your instance and the scheduler is never allowed to place another tenant on them.

That pinning is what eliminates %st (steal) from top. You can see the current value directly:

top -bn1 | grep "Cpu(s)"
# look for the st% field
vmstat 1 5 | awk 'NR==1 || NR>2 {print $1, $15}'   # column 15 = st

Database Workloads: Where Dedicated Cores Pay Off

Database engines are latency-shaped, not throughput-shaped. A PostgreSQL or InnoDB backend holds a lock for a fixed number of operations, and that critical section runs on one core. When steal interrupts it, the lock is held longer, other transactions queue behind it, and tail latency inflates faster than average CPU usage suggests. This is why a database can show only 45% CPU utilization yet exhibit 3x worse p99 latency under contention.

For read-heavy web workloads you can often absorb this. For write-heavy or OLTP databases, the isolation premium is the cheapest latency insurance you can buy. The same logic applies to anything with a serialized critical path: Redis with persistence enabled, game-server tick loops, and message brokers.

Web and Application Workloads: Where Sharing Is Usually Fine

PHP-FPM workers, Node.js request handlers, and static file servers are horizontally parallel. If a vCPU is descheduled for 4 ms, another worker on a different vCPU keeps draining the accept queue. Users see a marginally slower request, not a stalled system. Bursty traffic is absorbed by a worker pool that is provisioned for the peak anyway.

For these workloads, spending 30% more on a VDS usually buys nothing measurable. You are better off spending that budget on more RAM for page cache or on a CDN in front of the origin. This is exactly the trade-off explored in our write-up on the practical benefits of cloud VPS capacity — burstable shared capacity handles spiky web traffic well.

Measuring the Difference Yourself

Do not trust marketing numbers. Reproduce the comparison on the instance class you are actually considering. A paired test that isolates scheduling jitter from raw core speed:

# 1. Raw single-core speed
sysbench cpu --threads=1 --time=30 run

# 2. Scheduling jitter under contention (the isolation test)
sysbench cpu --threads=$(nproc) --time=60 run

# 3. Tail latency while CPU is pegged
taskset -c 0 stress-ng --cpu 1 --timeout 60s &
for i in $(seq 1 200); do
  S=$(date +%s%N); sleep 0.01; E=$(date +%s%N)
  echo $(( (E-S)/1000 ))
done | sort -n | awk '{a[NR]=$1} END {print "p99 (us):", a[int(NR*0.99)]}'

The third test is the decisive one. On a quiet VDS the p99 sleep overshoot stays within tens of microseconds of the 10 ms target. On a contended VPS it routinely spikes into the low milliseconds.

Workload-to-Instance Decision Matrix

WorkloadLatency-sensitive?RecommendedWhy
Static / CMS web servingNoVPSParallel workers absorb jitter
Node.js / PHP APILowVPSWorker pool masks steal
PostgreSQL / MySQL OLTPHighVDSLock hold time inflates p99
Redis with AOF/RDBHighVDSSerialized persistence path
Game server tick loopHighVDSFixed 16.6 ms frame budget
CI runners / batch jobsNoVPSThroughput, not latency

Memory and Disk Isolation by Workload

CPU is only one axis. Databases are also the first to suffer from memory overcommit and burst IOPS caps. Many VPS plans oversell RAM using ballooning and KSM, so free -h reports 4 GB while the host reclaims pages under pressure. A database that suddenly loses its page cache falls back to disk reads and its throughput collapses — even though nothing in your own load changed.

grep -E 'MemTotal|MemAvailable|Committed_AS|CommitLimit' /proc/meminfo
dmesg | grep -i -E 'balloon|oom|kcompactd'

Web tiers are far more forgiving: they are stateless, can be restarted, and lose nothing when the kernel reclaims cache. Database workloads hold state and care deeply. Combine that with disk — a plan capped at 3,000 IOPS will starve InnoDB or PostgreSQL checkpoints long before its CPU is busy. For a database, always measure random-read IOPS with fio --rw=randread --bs=4k --iodepth=32 before trusting the storage label.

A Practical Migration Path

  • Start on VPS. Run your database and web tier on shared vCPUs and record p99 latency at peak for two weeks.
  • Watch steal, not utilization. If %st exceeds 5% during your peak window, the scheduling layer — not your code — is adding latency.
  • Split the tiers. Move only the latency-sensitive process (the database) to a VDS and leave the web tier on the cheaper VPS.
  • Re-measure. Confirm the p99 improvement is at least 20% before extending the VDS contract.

Takeaway

Isolation is a workload-specific purchase. Databases, brokers, and anything with a serialized critical path benefit from pinned cores; web servers, APIs, and batch jobs usually do not. Benchmark your own workload with the tests above, then check the current VPS and VDS plans and pick isolation only for the tier that actually feels the jitter.

Leave a Reply