Proxmox VEII · Production PlanningReference architectures
Capacity planning and N+1 design
What you'll learn
- Translate a workload inventory into per-node sizing
- Compute N+1 headroom for HA failover
- Plan storage capacity with growth and replication overhead
- Recognise when a cluster has outgrown its capacity
- Apply the survivable-ceiling rule N x u / (N - 1) rather than the two-node 50% rule
- Separate guest demand, which fails over, from per-node overhead, which does not
Prerequisites
Verified against Proxmox VE 9.2.4 · Proxmox Backup Server 4.2.5 · Ceph Squid / Tentacle · Debian 13 (Trixie) · Linux kernel 7.0 (PVE 9.2 default) · 2026-08-12
Why this matters in production
Capacity exhaustion is one of the most preventable outage causes. A cluster that runs at 95 % utilisation has no headroom for HA failover, no room for growth, and no slack for maintenance windows. The cost of buying more capacity now is always less than the cost of an outage later.
Mental model
Three numbers drive every sizing decision:
- Sum of workload requirements — total vCPU, RAM, IOPS, storage the business needs.
- Headroom for growth — the multiplier on top of (1) for the planning horizon.
- N+1 (or N+2) for HA — capacity to run the full workload minus one node (or two).
flowchart LR
A[Workload inventory] --> SUM[Sum of requirements]
G[Growth target] --> SUM
SUM --> PER[Per-node requirement]
HA[HA headroom: N+1 or N+2] --> PER
PER --> NODES[Node count]
Worked example
Workload inventory (simplified):
| VM | vCPU | RAM (GB) | IOPS | Storage (GB) |
|---|---|---|---|---|
| web-01 | 4 | 8 | 800 | 50 |
| web-02 | 4 | 8 | 800 | 50 |
| db-01 | 8 | 32 | 8000 | 500 |
| app-01 | 4 | 16 | 1200 | 100 |
| app-02 | 4 | 16 | 1200 | 100 |
| util | 2 | 4 | 200 | 20 |
| Sum | 26 | 84 | 12 200 | 820 |
Target: 40 % growth over three years. N+1 (cluster of 3 nodes, can lose 1).
After growth multiplier (×1.4):
- Total vCPU: 26 × 1.4 ≈ 37
- Total RAM: 84 × 1.4 ≈ 118 GB
- Total IOPS: 12 200 × 1.4 ≈ 17 100
- Total storage: 820 × 1.4 ≈ 1 150 GB
The cluster has 3 nodes and must keep running with 2. So each node must be sized to carry
its share when there are only 2 nodes left — divide by N − 1, which is 2, not by 3
and not by the survivable-ceiling percentage:
- Per-node vCPU: 37 / 2 ≈ 19
- Per-node RAM: 118 / 2 = 59 GB
- Per-node IOPS: 17 100 / 2 ≈ 8 600
- Per-node storage: 1 150 / 2 ≈ 575 GB
This is the per-node requirement. Each node must be sized to handle its share during a node failure, not during normal operation.
Interactive · Capacity Planner
Sketch a workload inventory and see the cluster sizing implications, including N+1 HA headroom and a configurable growth multiplier.
Workload inventory
| Name | vCPU | RAM (GB) | IOPS | Storage (GB) | |
|---|---|---|---|---|---|
Sizing recommendations
- Cluster nodes
- 4
- vCPU per node
- ~13
- RAM per node
- ~40 GB
- IOPS per node
- ~5694
- Storage per node
- ~383 GB
Includes 40% headroom for growth and 1 spare node for HA failover capacity.
The survivable ceiling
The N+1 requirement above has a direct expression as a utilisation limit. With N nodes
each at utilisation u, one failure spreads N × u over N − 1 survivors:
per-node load after one failure = N x u / (N - 1)
Set that to 100 % and solve for u:
| Nodes | Ceiling per node | Survivors after one failure |
|---|---|---|
| 2 | 50.0 % | 100 % |
| 3 | 66.7 % | 100 % |
| 4 | 75.0 % | 100 % |
| 5 | 80.0 % | 100 % |
| 6 | 83.3 % | 100 % |
The ceiling rises with node count, because each survivor absorbs a smaller share. That is the capacity argument for larger clusters, independent of the availability one.
Per-node overhead does not fail over
The arithmetic above treats the whole workload as mobile. Part of a hyper-converged node’s load is not.
When a node dies its guests move to the survivors. Its Ceph OSDs, its pvedaemon, its ZFS
ARC and its kernel are simply gone — and every surviving node is still running its own. So
the per-node requirement is:
capacity per node >= guest demand / (N - 1) + per-node overhead
For a hyper-converged node, budget roughly 1 core and the osd_memory_target (4 GiB by
default) per Ceph OSD, plus a couple of cores and 8 GiB for PVE and the kernel. Recovery
after a failure makes that overhead heavier at exactly the moment guest demand rises,
which is one reason to design to 90 % after a failure rather than 100 %.
N+1 vs N+2
| Pattern | Survives | Cost | Use |
|---|---|---|---|
| N+1 (3 nodes) | 1 node failure | Low | Most production clusters |
| N+2 (5 nodes) | 2 simultaneous failures | Higher | Mission-critical, rolling maintenance |
| 2-node + QDevice | 1 node failure (with QDevice tiebreaker) | Lowest | Edge sites, branch offices |
Storage capacity calculation
For Ceph, raw capacity is not the same as usable capacity. With size=3 replication:
usable = (raw capacity) / replication factor
A 3-node Ceph cluster with 4 × 1 TB SSDs per node has 12 TB raw, and every object is stored three times, so roughly 4 TB is usable. Two further reductions apply before you can allocate any of it:
- The near-full ratio. Ceph’s default
nearfull_ratiois 0.85 andfull_ratiois 0.95; crossing full stops writes cluster-wide. Divide by 0.85 to get the raw capacity you must actually own. - Re-replication after a failure. When a node is lost, Ceph restores the third copy onto
the survivors. So the raw requirement has to be met by
N − 1nodes, not by allN. A cluster sized across all three has room for the data and no room to make the copy again, and stays degraded until someone buys disks.
raw required = usable x size / nearfull_ratio, present on (N - 1) nodes
For ZFS local storage:
usable = (raw capacity) - (parity overhead) - (slop for snapshots, copies)
A 4-disk RAIDZ2 has 50 % usable capacity; reserve 20 % for snapshots, copy-on-write fragmentation, and copy-on-write overhead.
The output of a capacity plan is a date
A single utilisation figure is not a finding. 60 % is healthy, and 60 % is also a countdown; only the growth rate distinguishes them.
Take the 3-node cluster above with a 66.7 % ceiling and 20 % annual growth from 50 % per node:
- Year 0: 50 % — comfortable.
- Year 1: 60 % — still under the ceiling.
- Year 2: 72 % — past it. A single failure is now an outage.
So the useful output is “a fourth node must be in service before year 2”. That is something a budget cycle can act on, by someone who does not operate the cluster. A utilisation percentage is not.
Run the same arithmetic for every dimension — cores, memory, storage, IOPS — and the plan expires on the earliest of them. It is frequently not the one being watched.
Common mistakes
- Sizing for normal operation, not failover. A cluster that fits all VMs on 3 nodes is at 100 % utilisation — it cannot lose a node.
- Dividing by
N × ceilinginstead of byN − 1. The ceiling checks an existing design; it is not a sizing divisor. - Quoting the two-node 50 % rule at a larger cluster. The ceiling is
(N−1)/N. - Treating per-node overhead as mobile. Ceph OSDs and host daemons do not fail over, and recovery makes them heavier during the failure.
- Forgetting that ZFS snapshots and Ceph replication consume capacity that is not “data” but is still on the disks.
- Sizing Ceph raw capacity across all
Nnodes rather than the survivors. - Assuming growth is linear. Three years at 15 % is 52 %, not 45 % — and cloud-native workloads often grow in steps rather than smoothly (a new application launches; all of a sudden the cluster is full).
- Reporting a utilisation figure instead of a date.
Key takeaways
- Size per node for the workload spread over
N − 1nodes, plus the per-node overhead that does not move — that is HA headroom. - The survivable ceiling is
(N−1)/N: 50 % at two nodes, 66.7 % at three, 75 % at four, 80 % at five. It rises with node count. - The ceiling is where a failure becomes an outage, not where to operate. Set the target below it.
- Include a growth multiplier explicitly, and compound it.
- For Ceph,
raw = usable × size ÷ nearfull_ratio, and it must fit on the survivors. - Alert on after-failure utilisation, not current utilisation.
- Deliver a date, not a percentage.
Production considerations
Knowledge check
Knowledge check · 5 questions
Q1. A 3-node cluster must fit its workload on 2 nodes when one is down. The total workload requires 100 vCPU. What is the minimum per-node vCPU?
Q2. Which of the following should appear in a capacity-planning spreadsheet? (Select all that apply.)
Q3. A Ceph pool with size=3 yields roughly one third of raw capacity as usable, and less once full-ratio headroom is reserved.
Q4. A 3-node cluster runs at 80 % of every capacity dimension. A colleague cites the "80 % rule" and says this is fine. What is wrong with that?
Q5. Why should per-node overhead such as Ceph OSD daemons be added separately rather than included in the workload total that gets divided by N-1?
Passing score: 75%. Answers are checked in this browser.