When teams migrate off VMware or escape the lottery of shared VPS tiers, they tend to carry their old sizing habits with them. The instinct is understandable: if 8 vCPUs kept things stable on a noisy shared host, why shrink the allocation on a VDS that promises reserved resources? Because the logic that drove over-provisioning on shared infrastructure actively works against you on a virtual dedicated server, and the performance penalty is real.

A VDS reserves its full allocation of cores and memory at the host level. That guarantee eliminates the neighbour-noise problem that made oversizing a reasonable hedge on a VPS, but it does not change how the hypervisor schedules threads or how the guest OS manages memory pressure. The resource guarantee is at the allocation layer, not the bare-metal isolation layer. Sizing decisions still matter, and on a VDS they matter more, because you are paying for a specific allocation and the hypervisor is working with exactly what you gave it.

The two failure modes are mirror images of each other: under-allocate and you starve the workload; over-allocate and you introduce scheduling overhead, memory waste, and in some configurations genuine latency regressions. Both are common in the first weeks after a migration.

The CPU overcommit trap

VDS instances run on hypervisors, typically KVM, Xen, or Hyper-V. The hypervisor schedules vCPUs against physical cores, and the ratio between the two determines whether that scheduling is transparent or a source of contention. Red Hat’s RHEL 9 documentation puts the safe ratio at roughly 5 vCPUs per physical core for workloads running below 100% utilisation, and explicitly warns against exceeding 10 vCPUs per physical core under any production conditions. VMware-focused guidance is broadly consistent: ratios above 3:1 begin to show measurable degradation, and 6:1 is where significant degradation becomes expected.

The counterintuitive part is what happens when you assign more vCPUs than a workload actually uses. XenServer’s own documentation states that for best performance, the number of vCPUs assigned should not exceed the number of physical CPUs available to the VM. The reason is scheduling: a VM with 8 vCPUs requires the hypervisor to find 8 simultaneous physical thread slots before it can run a scheduled event. A VM with 2 vCPUs running the same workload will often get scheduled faster, with lower latency on individual operations. Over-allocation does not add headroom; it adds scheduling debt.

Assigning more vCPUs than a workload consumes does not add headroom. It adds scheduling overhead, and on a lightly loaded workload, it can measurably increase latency.

Hyperthreading complicates this further. The performance gain from hyperthreading is real but bounded: official guidance puts the ceiling at around 30%, and it is strongly application-dependent. A CPU-bound workload with high thread contention may see no gain at all, or a regression, if the scheduler is filling physical threads with competing vCPU demand.

Reading steal time before you resize

If you are migrating from a shared VPS and suspect your previous host was overselling capacity, steal time is the metric to check before you replicate the old allocation on your new VDS. Steal time, reported as %st in the CPU section of top on Linux guests, measures the percentage of time the VM process is waiting on the physical CPU for its turn. It is a direct signal of host-level contention.

The published thresholds converge around the same picture: below 5% is normal and acceptable; 5 to 10% is worth monitoring; above 10% means noticeable slowdowns are likely and the allocation or host placement needs attention. A 4-core VDS on an oversold host can lag behind a well-provisioned 2-core box running the same workload. Core count on paper means nothing if steal time is high.

One important caveat: standard OS reporting tools were not designed for virtualised environments, and steal time readings can occasionally be false positives, particularly when the guest is largely idle. The reliable signal is sustained high steal time combined with a near-zero idle percentage. If both conditions are present over a meaningful observation window, the workload is genuinely being delayed at the host level. On a properly provisioned VDS, sustained steal above 5% should be rare; if it is not, the conversation needs to move to host placement, not just guest sizing.

Memory: working set first, overhead second

VMware’s vSphere 8.0 performance guide frames memory sizing cleanly: allocate enough memory to hold the working set of the applications running in the VM, and no more. Memory beyond the working set ends up used by the guest OS as file-system cache, which is not useless, but it is not the reason you sized the instance. When host memory pressure rises, the hypervisor will reclaim that cache memory through ballooning before it touches application memory, but over-allocating to begin with raises the memory overhead for the VM and increases the risk of swapping under peak load.

The practical target from vSphere guidance: keep commitment at roughly 90% of allocated memory rather than 100%, which leaves the hypervisor room to manage pressure without triggering swap. NUMA layout also matters here. On multi-socket hosts, memory accesses that cross NUMA boundaries carry a latency penalty. A VM sized to fit within a single NUMA node will see more consistent memory latency than one that spans nodes, and this is worth asking about when selecting an instance tier for latency-sensitive workloads.

A practical sizing workflow for VDS migrations

The right sequence for VDS resource allocation is: measure first, allocate second, and verify before you lock in the size.

  1. Profile the workload on the old host. Collect CPU utilisation, memory working set, and steal time over at least a week, covering any batch jobs or traffic peaks. This is the baseline you are actually sizing for, not the peak you feared on a shared host.
  2. Start conservative on vCPUs. Match vCPU count to actual peak thread utilisation, not to what you had before. A workload that peaks at 60% on 4 vCPUs is a candidate for 4 vCPUs, not 8. You can scale up; the cost of over-allocation is paid continuously.
  3. Size memory to the working set, not the installed RAM on the old host. Check balloon driver activity and swap usage on the old environment. If ballooning was never triggered, the allocation was already generous. Right-size to observed working set plus a reasonable headroom margin, targeting 90% commitment.
  4. Verify with %st and memory pressure metrics after deployment. Run the workload for at least 48 hours under realistic load before treating the sizing as final. Steal time above 5% sustained, or swap activity under normal load, are signals to revisit either the allocation or the host placement.

Where placement matters as much as allocation

Resource allocation decisions do not exist in isolation from where the VDS actually runs. For finance and industrial workloads in the DACH region, we place latency-sensitive VDS instances at MUC1 in Munich, where the cluster is specifically built around that customer profile and the physical density is managed accordingly. The same allocation on a host that is poorly matched to the workload type will perform differently than on one tuned for it. This is not a feature of any individual VDS tier; it is a consequence of how host capacity is planned and what workloads share a physical machine.

The discipline of VDS resource allocation is ultimately the discipline of knowing what your workload actually does, not what it did on infrastructure designed to compensate for unpredictable neighbours. Reserved resources are only as valuable as the accuracy of the allocation. Measure the real profile, size to it, and the performance difference from a shared VPS tier becomes immediately apparent in the metrics that matter: p99 latency, scheduler wait time, and memory pressure under load.