Intro
Proxmox capacity planning is the process of estimating and validating the compute, memory, storage, and network resources your virtual machines (VMs) and containers will consume—and ensuring your Proxmox hosts can deliver those resources reliably over time. Without a systematic approach, you risk over‑provisioning (wasting budget) or under‑provisioning (causing performance degradation, crashes, or unplanned downtime).
This guide is written for developers, DevOps consultants, and technical startup teams who run Proxmox VE in production or are planning to. It focuses on practical, hands‑on capacity planning using Proxmox’s native tools: the web UI, the pvesh API, and command‑line utilities like pveperf, qm, and pct. You’ll learn how to baseline current usage, size new workloads, set sensible limits, and validate your plan before deploying.
The core principle is operational safety: observe before changing, limit the blast radius, use placeholders instead of real identifiers in shared examples, verify every result, and document recovery steps. By the end, you’ll have a repeatable checklist for capacity planning in any Proxmox environment.
1. Version and Environment Inventory
Before you can plan capacity, you must know exactly what you’re working with. Proxmox versions differ in available features, default settings, and performance characteristics. Start by gathering the following information from each node in your cluster:
- Proxmox VE version and repository status
- CPU model, core count, and current load
- Total and used RAM
- Storage types (local LVM, ZFS, Ceph, NFS, etc.), capacity, and usage
- Network interface speeds and current throughput
- Number and type of running guests (VMs and containers)
Read‑only observation commands
Run these commands on a Proxmox node to collect a baseline without changing anything:
# Proxmox version and repository info
pveversion -v
# Cluster status (if clustered)
pvecm status
# CPU and memory summary
lscpu | grep -E 'Model name|CPU\(s\)|Thread|Core|Socket'
free -h
# Storage usage per pool
pvesm status
# Detailed storage list with type and capacity
pvesh get /storage --output-format json
Example output from pvesm status:
Name Type Status Total Used Available %
local dir active 98497780 3821376 89635012 3.88%
local-lvm lvmthin active 1073741824 268435456 805306368 25.00%
ceph‑pool rbd active 21474836480 5368709120 16106127360 25.00%
Interpretation: local is the root filesystem, local-lvm is thin‑provisioned LVM storage for VM disks, and ceph‑pool is an RBD pool if you use Ceph. The % column shows current utilisation. For capacity planning, you need both the current usage and the growth trend.
Prerequisites and blast radius
- Prerequisites: SSH access to the node with a user that has
PVEAdminor at leastPVEAuditorrole for read‑only commands. ForpveshAPI calls, you need an API token with appropriate permissions (never use the root password in scripts). - Blast radius: These commands are read‑only and safe to run at any time. They do not modify configuration or affect running guests.
- Verification: After running each command, confirm the output matches your expected inventory. For example, if you expect 128 GB RAM but
free -hshows 64 GB, investigate before proceeding.
Example: building a node inventory snapshot
Create a simple script that writes the output of these commands to timestamped files for later comparison:
#!/bin/bash
# inventory_snapshot.sh – run as root on each Proxmox node
DATE=$(date +%Y%m%d_%H%M%S)
OUTDIR=/var/log/proxmox-inventory
mkdir -p $OUTDIR
{
echo "=== pveversion =="
pveversion -v
echo "=== lscpu =="
lscpu
echo "=== free -h =="
free -h
echo "=== pvesm status =="
pvesm status
echo "=== qm list =="
qm list
echo "=== pct list =="
pct list
} > $OUTDIR/inventory_$DATE.txt
Schedule this script via cron to run daily. Over time, you’ll have historical data to observe trends.
2. Safe Configuration Path
Capacity planning often involves changing resource allocations: adding CPUs, increasing RAM, extending disks, or adjusting limits. The “safe configuration path” means you make changes in a controlled, reversible manner.
Naming components and version range
All examples in this guide are for Proxmox VE 7.x and 8.x. Commands may differ slightly in older versions—always check the official documentation for your specific release.
Before you change: record current state
For any guest (VM or container) you plan to modify, capture its current configuration and resource usage:
# For VM with ID 100
qm config 100
qm status 100 --verbose
# For container with ID 101
pct config 101
pct status 101 --verbose
Example output for qm config 100:
boot: order=scsi0;net0
cores: 2
memory: 4096
name: web‑server
net0: virtio=BC:24:11:AA:BB:CC,bridge=vmbr0
scsi0: local‑lvm:vm‑100‑disk‑0,size=32G
sockets: 1
Smallest justified change
Rather than jumping from 2 cores to 8, increase resources incrementally and measure impact. For example, if a VM is consistently hitting 100% CPU during peak hours, adding one core (or moving from 1 socket/2 cores to 1 socket/3 cores) might suffice.
Change example: increase RAM for VM 100 from 4 GB to 6 GB
- Observation: Use
qm status 100 --verboseto confirm current memory allocation and actual usage viaqm guest cmd 100 summary(if guest agent is installed) or host‑level monitoring. - Prerequisites: VM must be powered off to change memory unless hotplug is enabled. Check hotplug support:
qm config 100 | grep hotplug. Ifhotplug: 1is present, you can change RAM while running. - Command (offline change):
qm set 100 --memory 6144
For online change with hotplug:
qm set 100 --memory 6144
qm monitor 100 -c 'balloon 6144' # if ballooning is enabled
- Verification:
qm config 100 | grep memory
# Should show memory: 6144
qm status 100 --verbose | grep maxmem
# Should reflect new maximum
- Recovery path: Revert to original value:
qm set 100 --memory 4096
Blast radius and rollback
When modifying storage, be extra careful. Extending a disk is usually irreversible (you can’t shrink a disk easily), so always snapshot before changes if possible:
# If using ZFS or LVM‑thin, snapshot the VM disk
qm snapshot 100 pre_resize_snapshot
If the change causes issues, roll back:
qm rollback 100 pre_resize_snapshot
3. Sizing New Workloads: Worked Examples
Capacity planning isn’t just about current usage—it’s about predicting what new workloads will need. Here are three common scenarios with concrete numbers.
Example 1: Sizing a web application VM
You’re deploying a typical LAMP stack web server expecting moderate traffic. Based on your application’s benchmark or documentation:
- CPU: Estimated need: 2 vCPUs at average 50% load. Proxmox rule of thumb: allocate 1 vCPU per physical core if possible, but overcommitment up to 2:1 is usually safe for non‑CPU‑intensive workloads. So 2 vCPUs is fine.
- RAM: Web server + MySQL + PHP: 2 GB for OS, 2 GB for MySQL buffer, 1 GB for web/PHP processes. Total 5 GB, round up to 6 GB.
- Storage: OS disk 20 GB, application and logs 10 GB, database files 30 GB. Total 60 GB. With LVM‑thin provisioning, you can allocate 60 GB now and grow later.
- Network: 100 Mbps peak expected. Virtio NIC can handle gigabit easily.
Proxmox configuration command:
qm create 200 --name webapp --memory 6144 --cores 2 --sockets 1 \
--net0 virtio,bridge=vmbr0 --scsihw virtio-scsi-pci \
--scsi0 local-lvm:60,format=qcow2
Verify: qm config 200 and check that all values are as intended.
Example 2: Sizing a database server (PostgreSQL)
Database servers are RAM‑ and storage‑I/O‑intensive. Suppose you have a 100 GB database with 200 transactions per second.
- RAM: PostgreSQL recommends shared_buffers ~25% of RAM. For a 64 GB host, 16 GB shared_buffers, plus 8 GB for OS and connections, total 32 GB for the VM.
- CPU: 8 vCPUs to handle concurrent queries (depending on workload, 4–8 is typical).
- Storage: Use fast storage (SSD or NVMe). Allocate 200 GB to allow for growth and temporary files. If using Ceph RBD, ensure the pool has enough IOPS.
- Disk I/O limit: Set a limit if shared storage to prevent noisy neighbour issues:
qm set 300 --drive scsi0,disk-iops-limit=5000
Create VM:
qm create 300 --name postgres --memory 32768 --cores 8 --sockets 2 \
--net0 virtio,bridge=vmbr0 --scsihw virtio-scsi-pci \
--scsi0 ceph-pool:200,format=raw
Example 3: Sizing a container for a microservice
Containers (LXC) are lighter than VMs. For a Node.js microservice with modest needs:
- CPU: 1 vCPU, but allow burst. Set CPU limit to 50% of one core and allow 2 cores if needed:
pct set 400 --cores 2 --cpulimit 1
Here --cores 2 gives access to 2 cores, --cpulimit 1 limits total CPU time to 100% of one core.
- RAM: 512 MB minimal, allow swap 256 MB:
pct set 400 --memory 512 --swap 256
- Storage: 5 GB rootfs on local-lvm.
Create with:
pct create 400 local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst \
--hostname microservice --memory 512 --swap 256 --cores 2 --cpulimit 1 \
--rootfs local-lvm:5 --net0 name=eth0,bridge=vmbr0,ip=dhcp
4. Capacity Planning Formulas and Thresholds
Beyond individual VMs, you need to plan at the host and cluster level. Here are key formulas and recommended thresholds.
CPU overcommit ratio
Physical cores vs. allocated vCPUs. Recommended maximum overcommit:
- For general workloads: 2:1 (e.g., 32 physical cores can host 64 vCPUs)
- For CPU‑intensive workloads: 1:1 (no overcommit)
- For light/idle workloads: 4:1 possible
Calculate current ratio:
# Sum of vCPUs allocated
sum_vcpus=$(qm list | awk '{print $3}' | grep -E '^[0-9]+$' | paste -sd+ | bc)
# Physical cores
physical_cores=$(lscpu | grep '^CPU(s):' | awk '{print $2}')
echo "Allocated vCPUs: $sum_vcpus, Physical cores: $physical_cores, Ratio: $(echo "scale=2; $sum_vcpus/$physical_cores" | bc)"
Keep this ratio below your chosen threshold. For example, if 32 physical cores and 48 vCPUs allocated, ratio = 1.5, which is acceptable for general workloads.
Memory overcommit
Proxmox allows memory overcommit, but you must monitor actual usage. Host should always have at least 10–20% free RAM plus room for virtualisation overhead (usually 1–2 GB per host, plus 200–500 MB per VM).
Check host memory pressure:
free -h
cat /proc/meminfo | grep -E 'MemAvailable|SwapTotal|SwapFree'
If MemAvailable drops below 10% of total, you’re at risk.
Storage capacity and growth
Plan storage capacity with headroom. A simple formula:
Required capacity = Current usage + (Projected annual growth × 1.5) + 20% buffer
For example, if current VM disk usage is 2 TB, annual growth is 500 GB, then:
- Next year’s additional need: 500 GB × 1.5 = 750 GB
- Buffer: 20% of (2 TB + 750 GB) = 550 GB
- Total capacity: 2 TB + 750 GB + 550 GB = 3.3 TB
- Round up to RAID array size (e.g., 4 TB usable).
Network bandwidth planning
Estimate peak network throughput for all guests. For example, 10 VMs each requiring 100 Mbps = 1 Gbps aggregate. Your host NIC should support at least this, plus overhead. Bond multiple NICs if necessary.
5. Monitoring and Trending for Capacity Planning
Capacity planning is an ongoing process, not a one‑time event. Set up monitoring to collect historical data and alert on trends.
Built‑in Proxmox monitoring
Proxmox provides RRD graphs in the web UI (per node and per guest). For long‑term trending, use an external system like Prometheus + Grafana. Proxmox exposes metrics via the API.
Enabling the built‑in metrics exporter (optional)
Proxmox 8 can send metrics to InfluxDB or Prometheus. Configure in /etc/pve/status.cfg to use InfluxDB:
influxdb: influxdb
server 10.0.0.5
port 8089
protocol udp
Then restart pvestatd. For Prometheus, use the external prometheus-pve-exporter.
Sample Prometheus query for capacity
If using the pve exporter, you can query:
# Host CPU utilisation percentage
100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# Memory available percentage
(node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100
Set alerts when these cross thresholds (e.g., CPU > 85% for 15 minutes, memory available < 10%).
Log and performance analysis
Use iostat, vmstat, and sar on the host to identify I/O bottlenecks:
iostat -x 1 5
vmstat 1 5
If storage latency (await) is consistently high (>20 ms for HDD, >5 ms for SSD), you may need faster disks or Ceph tuning.
6. Failure Modes and Recovery
Capacity planning must account for failures. Here are common failure modes and how to prepare.
Out‑of‑memory (OOM) on host
Symptom: Host becomes unresponsive, VMs are killed randomly. Proxmox uses the OOM killer when host memory is exhausted.
Prevention:
- Enable memory ballooning on VMs.
- Set minimum memory guarantees for critical VMs.
- Ensure host memory overcommit ratio is not too high.
Detection:
dmesg | grep -i 'out of memory'
journalctl -k | grep -i oom
Recovery:
- Power off non‑critical VMs to free memory.
- Increase host RAM (hardware change).
- Adjust VM memory allocations to reduce overcommit.
Disk full on storage pool
Symptom: VMs can’t write, ENOSPC errors in guest, Proxmox may pause VMs.
Prevention:
- Monitor storage usage and set alerts at 80%.
- Use thin provisioning cautiously; track actual usage.
- Schedule regular cleanup of snapshots, backups, and ISO images.
Detection:
pvesm status
If any pool is >80% full, act.
Recovery:
- Delete old snapshots:
qm delsnapshot <vmid> <snapname> - Move disks to another storage:
qm move-disk <vmid> <disk> <target-storage> - Expand underlying storage (add disks to LVM/ZFS, expand Ceph OSDs).
Network saturation
Symptom: High latency, packet loss, slow VM network.
Prevention:
- Use separate networks for storage (Ceph) and VM traffic.
- Monitor NIC throughput.
Detection:
iftop -i vmbr0
Recovery:
- Move heavy VMs to different hosts.
- Add NIC bonding or upgrade to 10G.
CPU starvation
Symptom: VMs sluggish, host load average high.
Detection:
uptime
top
If load average > physical cores for sustained period, you’re overcommitted.
Recovery:
- Reduce vCPU count on low‑priority VMs.
- Migrate VMs to less loaded hosts.
- Add more physical cores (if possible).
7. Operations Checklist
Use this checklist before and after making capacity changes to ensure safety and consistency.
Before any change
- [ ] Record current node and guest state (commands from Section 1).
- [ ] Confirm Proxmox version and note any version‑specific behaviour.
- [ ] Identify the exact resource to change (CPU, RAM, disk, network).
- [ ] Calculate the new value based on observed need and headroom.
- [ ] Check current overcommit ratios (CPU, memory) to ensure the addition won’t push over threshold.
- [ ] If changing disk, create a snapshot if possible.
- [ ] Document the rollback command and original value.
- [ ] Schedule a maintenance window if a reboot is needed.
During change
- [ ] Execute the change command (e.g.,
qm set) and note the output. - [ ] If using the web UI, double‑check the values before applying.
After change
- [ ] Verify the new configuration with read‑only commands (e.g.,
qm config). - [ ] Monitor the guest for a reasonable period (at least 15 minutes under load) to confirm improvement.
- [ ] Check host‑level metrics to ensure no adverse impact on other guests.
- [ ] Update documentation and monitoring thresholds if needed.
- [ ] If the change caused issues, roll back immediately using the documented recovery path.
Example checklist run for a RAM increase
- State record:
qm config 100 | tee /root/vm100_before.txt
qm status 100 --verbose | tee /root/vm100_status_before.txt
- Change:
qm set 100 --memory 8192
- Verify:
qm config 100 | grep memory
# Expected: memory: 8192
- Monitor: Use web UI or
qm monitorto watch memory usage. - Rollback if needed:
qm set 100 --memory 4096
8. Advanced Capacity Planning with Ceph
If you use Proxmox with Ceph hyper‑converged storage, capacity planning extends to OSD sizing and pool placement groups.
OSD capacity planning
Number of OSDs needed = (Total capacity required after replication) / (usable capacity per OSD).
Example: You need 10 TB usable with 3x replication. Raw capacity = 30 TB. If each OSD disk is 4 TB, you need 30/4 ≈ 8 OSDs, but consider node failure domains: typically minimum 3 nodes, with at least 4 OSDs per node for performance. So 3 nodes × 4 OSDs = 12 OSDs, providing 48 TB raw, 16 TB usable (after 3x replication).
Network for Ceph
Ceph cluster network should be at least 10 Gbps dedicated. Separate from VM traffic to avoid contention.
Monitoring Ceph capacity
Use ceph df to check usage:
ceph df
Output shows RAW and USED, and POOLS with USED and MAX AVAIL. Keep pool usage below 75% to avoid rebalancing issues.
9. Backup and Recovery Considerations in Capacity Planning
Backups consume storage space and CPU cycles. Include backup volume in your capacity plan.
Estimating backup space
If you run nightly backups of all VMs (using vzdump), you need enough storage for at least one full backup set, plus incremental changes if using PBS (Proxmox Backup Server).
Example: 10 VMs, average disk usage 50 GB each = 500 GB. Daily full backups with 7‑day retention = 3.5 TB. Deduplication in PBS can reduce this significantly, but plan for worst case.
Place backups on separate storage (NFS, dedicated backup server) to avoid impacting production storage.
Backup scheduling and I/O load
Schedule backups during off‑peak hours. vzdump can be CPU and I/O intensive. Use --ionice and --bwlimit to limit impact:
vzdump 100 --mode snapshot --compress zstd --storage backup-nfs \
--ionice 7 --bwlimit 102400
This limits backup I/O to 100 MB/s (102400 KB/s) and uses low I/O priority.
10. Tools and Commands Quick Reference
Here’s a summary of essential commands for capacity planning in Proxmox.
| Task | Command |
|---|---|
| Node CPU info | lscpu |
| Node memory | free -h |
| Storage pools | pvesm status |
| Node performance | pveperf (tests CPU, memory, disk) |
| List VMs | qm list |
| List containers | pct list |
| VM config | qm config <vmid> |
| Container config | pct config <ctid> |
| Change VM RAM | qm set <vmid> --memory <MB> |
| Change VM CPUs | qm set <vmid> --cores <n> |
| Extend VM disk | qm resize <vmid> <disk> <size> |
| Snapshot VM | qm snapshot <vmid> <snapname> |
| Rollback snapshot | qm rollback <vmid> <snapname> |
| Container resource limits | pct set <ctid> --cpulimit <limit> etc. |
| Ceph status | ceph -s, ceph df |
| Backup | vzdump <vmid> --mode snapshot |
| Host I/O stats | iostat -x |
| Network monitoring | iftop |
Conclusion
Proxmox capacity planning is an iterative discipline: measure, model, implement, and monitor. By following the practices in this guide—starting with a thorough environment inventory, using safe configuration changes, sizing new workloads with concrete examples, monitoring trends, and preparing for failures—you can maintain a stable and efficient virtualisation infrastructure.
The key takeaways:
- Always observe current state before making changes.
- Use version‑appropriate commands and placeholders in scripts.
- Calculate overcommit ratios and keep them within safe limits.
- Plan storage with growth and buffer.
- Implement monitoring and alerts for CPU, memory, storage, and network.
- Document rollback procedures for every change.
- Consider advanced scenarios like Ceph and backup storage in your capacity plan.
As a next step, pick one low‑risk verification task from this guide—for example, run pvesm status and check your storage utilisation against the 80% threshold, or calculate your current CPU overcommit ratio. Record the current state, run the check, and compare the result with the expected signal. Then, use that insight to make a small, well‑documented adjustment.
A reliable capacity planning process makes resource exhaustion visible before it becomes an incident, and gives you the confidence to scale your Proxmox environment safely.