A virtual dedicated server is a guarantee: your vCPUs and memory are not shared with other tenants. But that guarantee is a ceiling, not a floor. If the guest is configured without regard for CPU topology, NUMA alignment, and memory pinning, a significant fraction of that reserved capacity simply goes unused, or worse, actively hurts performance. The host honours the contract; the misconfiguration breaks it from the inside.

This is not a theoretical concern. Without proper CPU and NUMA configuration, virtual machines can experience cache thrashing, memory access penalties, and performance variability that reduces effective throughput by 50% or more. The physical resources are there. The problem is that nothing is telling the guest where they actually live.

Understanding why requires a short detour into how modern multi-socket servers actually work, and why the hypervisor’s default behaviour is optimised for density, not performance.

Why oversubscription is the default, and what VDS removes

On a standard cloud host, not all VMs need CPU cycles simultaneously. Hypervisors exploit this by scheduling vCPUs across any available physical core, supporting more vCPUs than physical threads in aggregate. This is overcommitment, and under light or bursty workloads it is entirely reasonable. A Dell vSphere white paper puts the practical thresholds plainly: a vCPU-to-pCPU ratio up to 3:1 is generally safe, 3:1 to 5:1 may begin to cause degradation, and 6:1 or greater is often going to cause a problem.

A VDS removes the overcommitment assumption entirely. Your vCPUs map to reserved physical threads; nobody else competes for them. But here is the catch: the hypervisor still schedules those vCPUs across whichever physical cores are available within the reservation, unless you explicitly tell it otherwise. The reservation prevents contention from other tenants. It does not, by itself, prevent the scheduler from bouncing your vCPUs between cores, between NUMA nodes, or across sockets.

The guarantee removes external interference. Misconfiguration reintroduces internal interference. Both cost you the same cycles.

NUMA topology: the hidden performance cliff

NUMA (Non-Uniform Memory Access) is the dominant memory architecture in any multi-socket server and in many high-core-count single-socket systems. Each CPU socket has its own local memory bank. Accessing local memory is fast; accessing memory attached to a different socket crosses an interconnect bus with limited bandwidth and meaningful latency.

The numbers are not abstract. A random memory access takes roughly 100 ns locally. Crossing to a remote NUMA node adds approximately 50% to that figure, according to ACM Queue’s overview of the architecture. Benchmarks using Intel Memory Latency Checker show remote NUMA access producing nearly twice the idle latency and about one-third the bandwidth of local access. For memory-intensive workloads, NUMA misalignment alone can reduce throughput by an average of 30%, with worst-case degradation reaching 51%.

When a VM runs without NUMA awareness, two separate topologies are in play: the physical NUMA layout of the host, and the virtual hardware topology exposed to the guest OS. If these do not align, the guest’s memory allocator makes decisions that look locally optimal but translate into remote-node accesses on the physical hardware. The guest thinks it is reading local memory; the hardware is crossing a bus.

Red Hat’s RHEL 9 documentation describes the goal precisely: configuring NUMA for VMs maps the host’s CPU and memory processes onto the VM’s CPU and memory processes as closely as possible, providing the vCPU with more streamlined access to the system memory allocated to the VM. This is not an optimisation for HPC clusters. It matters for databases, analytics, caching layers, and any service with memory in its critical path.

CPU pinning: what it does and how to get it right

CPU pinning binds each vCPU to a specific physical CPU thread. The scheduler stops rotating the vCPU across cores. Cache state built up on that core persists between scheduling intervals. Context switches no longer force cache repopulation from scratch.

The performance case for pinning is strongest when the host is fully loaded. For a system using all available CPU cores, CPU pinning improves application response time by eliminating rotations of processes among cores that cause unnecessary cache repopulations. It also eliminates the performance degradation that results from migrations between different NUMA nodes. Critically, pinning does not reduce the number of allowed CPU cores, so it does not introduce congestion on shared resources.

Getting pinning right on a VDS requires three steps done in order:

  1. Identify the host’s physical topology. Use lscpu, numactl --hardware, or lstopo to map which physical cores belong to which NUMA node and which socket. This is the ground truth your pinning configuration must reflect.
  2. Pin vCPUs to cores within a single NUMA node. If your VM has 8 vCPUs, pin all 8 to cores that share a NUMA node and a last-level cache. Spreading vCPUs across nodes for a single VM is the most common mistake: you get the worst of both worlds, neither the cache locality of a single node nor the bandwidth of a proper cross-node allocation.
  3. Align guest memory allocation to the same node. Pinning vCPUs without constraining memory allocation leaves the guest free to allocate on a remote node. Use numactl --membind or the equivalent hypervisor-level memory policy to bind guest memory to the same NUMA node as the pinned vCPUs. Without this step, pinning delivers half its potential benefit.

Workloads that pay the highest price for getting this wrong

Not every workload is equally sensitive. Latency-tolerant batch jobs absorb NUMA penalties reasonably well. The workloads that cannot are exactly the ones most commonly deployed on VDS: databases, in-memory caches, key-value stores, and microservices with tight tail-latency budgets.

Research on Azure production traces found that microservice, cache, and key-value workloads are among the most sensitive to oversubscription, with performance degrading by up to 2.35x in the worst case with fully oversubscribed VMs. These workloads access memory in the critical path, which means any added latency compounds across every request. A NUMA-misaligned Redis instance, for example, will show acceptable average latency while its p99 and p999 percentiles quietly climb. Average metrics hide the problem until it becomes a production incident.

The same principle applies to NUMA’s effect on tail latency. Average throughput can look fine while the tail is suffering. Monitoring average CPU utilisation on a misconfigured VDS will not reveal this. You need per-core utilisation, NUMA hit/miss ratios from perf stat or numastat, and memory bandwidth metrics to see what is actually happening.

Configuring a VDS correctly: a practical checklist

Before you tune anything, verify what you are working with:

  • Run numastat -m to check whether memory is being allocated on the correct node. A high numa_miss count means your allocator is already crossing nodes.
  • Check /proc/cpuinfo and cross-reference with numactl --hardware to confirm which logical CPUs share a physical core (hyperthreading siblings) and which share a NUMA node.
  • If you are running a KVM-based guest, verify that the VM’s XML definition includes a numatune block with mode='strict' and a nodeset that matches your pinned vCPUs.
  • For containerised workloads on a VDS, set CPU affinity at the cgroup level with cpuset.cpus and cpuset.mems, keeping both within the same NUMA node.
  • After any configuration change, re-run your application’s benchmark under realistic load. NUMA effects are workload-dependent; a synthetic microbenchmark may not reveal the same bottlenecks as a production query pattern.

We run DIVERSITY’s VDS product on non-oversubscribed hosts where physical CPU threads and memory are reserved per tenant, which means the topology information exposed to the guest reflects actual dedicated hardware rather than a virtualised approximation of a time-shared pool. That makes correct pinning configuration both more achievable and more consequential: the physical resources are genuinely there, so misconfiguration is the only thing standing between the guarantee on paper and the performance in production.

A VDS is not a performance guarantee by itself. It is a performance opportunity that correct configuration has to realise. Get the topology right, pin to a single NUMA node, bind memory to match, and the reserved capacity you are paying for will actually show up in your benchmarks.