Proxmox Memory Management: Ballooning, KSM, NUMA, and Overcommit
Optimize memory usage on Proxmox VE with ballooning, KSM kernel same-page merging, NUMA pinning, hugepages, and safe overcommit strategies. Includes monitoring commands and configuration examples.
How Proxmox Manages Memory
Memory is typically the most constrained resource on a Proxmox host. Unlike CPU, which can be time-sliced across guests with minimal penalty, memory is a hard physical limit. Proxmox provides several mechanisms to use memory more efficiently: ballooning dynamically adjusts guest memory, KSM deduplicates identical pages across VMs, NUMA pinning improves memory access latency on multi-socket systems, and hugepages reduce TLB misses for memory-intensive workloads. Understanding these tools helps you run more guests without hitting out-of-memory conditions.
Memory Ballooning
Ballooning allows Proxmox to reclaim unused memory from a VM and make it available to other guests. The guest OS runs a balloon driver that inflates (claiming guest memory) when the host needs it and deflates (releasing it back to the guest) when the host has memory available.
# Configure ballooning for a VM
# minimum = minimum guaranteed memory
# memory = maximum memory the VM can use
qm set 100 --memory 4096 --balloon 1024
# This means:
# - VM starts with up to 4 GB
# - Proxmox can reclaim down to 1 GB if other VMs need memory
# - The guest balloon driver handles the negotiation
# Check current balloon status
qm monitor 100
info balloon
# Shows current and maximum memory
# Ballooning requires the QEMU Guest Agent
# Install inside the VM:
# Debian/Ubuntu:
apt install qemu-guest-agent
systemctl enable --now qemu-guest-agent
# Verify the guest agent is communicating
qm agent 100 ping
# Check actual memory usage reported by the guest agent
qm agent 100 get-memory-blocks
Important: Ballooning works best on Linux guests. Windows VMs support ballooning but require the VirtIO balloon driver from the VirtIO drivers ISO. Without the balloon driver installed in the guest, the balloon device has no effect.
KSM (Kernel Same-Page Merging)
KSM scans memory pages across all VMs and merges identical pages into a single copy, using copy-on-write to handle modifications. This is especially effective when running many VMs with the same operating system, as kernel code, shared libraries, and idle memory pages are often identical.
# Check KSM status on the Proxmox host
cat /sys/kernel/mm/ksm/run
# 1 = enabled, 0 = disabled
# See how much memory KSM is saving
cat /sys/kernel/mm/ksm/pages_sharing
cat /sys/kernel/mm/ksm/pages_shared
# Calculate savings in MB
echo "$(( $(cat /sys/kernel/mm/ksm/pages_sharing) * 4 / 1024 )) MB saved by KSM"
# Enable KSM if disabled
echo 1 > /sys/kernel/mm/ksm/run
# Make it persistent across reboots
echo "ksm.run=1" >> /etc/sysctl.d/ksm.conf
# Tune KSM scan speed (pages per scan cycle)
cat /sys/kernel/mm/ksm/pages_to_scan
# Default: 100. Increase for faster merging (more CPU usage)
echo 200 > /sys/kernel/mm/ksm/pages_to_scan
# Check KSM CPU usage
# KSM runs as a kernel thread: [ksmd]
top -bn1 | grep ksmd
KSM trades CPU time for memory savings. On a host running 20 identical Debian VMs, KSM can save 30-50% of total VM memory. On a host with diverse workloads, savings are typically 5-15%.
Memory Overcommit Risks
Overcommitting memory means allocating more total memory to VMs than the host physically has, relying on ballooning and KSM to make this work. This is viable for lightly loaded VMs but dangerous if all VMs demand their full allocation simultaneously.
# Check current memory allocation vs physical RAM
# On the Proxmox host:
free -h
# Shows actual host memory usage
# Calculate total allocated to VMs
pvesh get /nodes/pve/qemu --output-format json | \
jq '[.[] | select(.status=="running") | .maxmem] | add / 1073741824'
# This shows total allocated GB
# Compare with physical RAM
grep MemTotal /proc/meminfo
# Signs of dangerous overcommit:
# - Host swap usage increasing
# - OOM killer activating (check dmesg)
dmesg | grep -i "out of memory"
# - VM performance degrading
# Safe overcommit ratio depends on workload
# Conservative: 1.2x (allocate 20% more than physical RAM)
# Aggressive: 1.5x-2x (only with ballooning and KSM active)
# Never exceed 2x without careful monitoring
NUMA Pinning
On multi-socket servers, each CPU socket has its own local memory. Accessing local memory is faster than accessing memory attached to a different socket (remote memory). NUMA pinning ensures a VM's memory is allocated from the same NUMA node as its assigned CPU cores.
# Check NUMA topology on the host
numactl --hardware
# Shows nodes, CPUs per node, and memory per node
# Enable NUMA for a VM
qm set 100 --numa 1
# Pin a VM to a specific NUMA node (node 0)
qm set 100 --numa0 cpus=0-7,memory=8192,hostnodes=0,policy=bind
# Verify NUMA assignment
qm config 100 | grep numa
# Monitor NUMA memory distribution
numastat -c qemu
NUMA pinning matters most for memory-intensive workloads like databases. On a dual-socket system, improper NUMA placement can reduce memory bandwidth by 20-40%.
Hugepages
Standard Linux memory pages are 4 KB. Hugepages (2 MB or 1 GB) reduce the number of page table entries the CPU must manage, improving performance for VMs with large memory allocations.
# Check current hugepage status
cat /proc/meminfo | grep -i huge
# Reserve 4 GB of 2 MB hugepages (2048 pages)
echo 2048 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
# Make persistent in /etc/sysctl.conf
echo "vm.nr_hugepages = 2048" >> /etc/sysctl.d/hugepages.conf
sysctl -p /etc/sysctl.d/hugepages.conf
# Verify allocation
grep HugePages /proc/meminfo
# HugePages_Total: 2048
# HugePages_Free: 2048
Monitoring Host Memory
Regular monitoring prevents memory problems from becoming emergencies.
# Quick memory overview
free -h
# Detailed breakdown
cat /proc/meminfo | head -20
# Per-VM memory usage
qm list | awk 'NR>1 {print $1}' | while read vmid; do
echo "VM $vmid: $(qm config $vmid | grep ^memory | awk '{print $2}') MB allocated"
done
# Watch memory in real time
watch -n 5 'free -h; echo "---"; cat /sys/kernel/mm/ksm/pages_sharing'
Keeping memory under control is especially important on single-node homelabs where there is no failover. If you use ProxmoxR to manage your Proxmox hosts, you can monitor memory utilization per VM and per node at a glance, making it easier to spot overcommit situations before the OOM killer intervenes.
Take Proxmox management mobile
All the features discussed in this guide — accessible from your phone with ProxmoxR. Real-time monitoring, power control, firewall management, and more.