Server Capacity Calculator

Servers needed = peak RPS ÷ (RPS one instance sustains within your latency target × target utilization), rounded up, plus enough spare capacity to survive losing an instance or a zone. With a 3,000 RPS peak, 20% growth, 400 RPS per instance and a 70% utilization target, you need ceil(3,600 ÷ 280) = 13 instances for normal running, and 15 spread across 3 zones so that losing a zone leaves the other 10 at 90%. The calculator below does the redundancy math; the per-instance number has to come from a load test.
The capacity formula
design_load = peak_RPS × (1 + growth%)
N_normal = ceil(design_load / (per_instance_RPS × target_util))
N_failure = ceil(design_load / (per_instance_RPS × failure_util))
None: total = N_normal
N+1: total = max(N_normal, N_failure + 1)
N+2: total = max(N_normal, N_failure + 2)
Zone: per_zone = max(ceil(N_normal / Z), ceil(N_failure / (Z − 1)))
total = Z × per_zone
Two utilization targets do different jobs. The normal target (often 60–75%) keeps latency flat during everyday bursts, because queueing delay grows quickly as a server approaches 100% busy; throughput vs latency shows the curve. The failure target is how hard you are willing to run the survivors for the minutes or hours until replacements arrive. It can be higher, but should stay below the point where your load test showed latency breaking the SLO.
Zone redundancy is usually what drives the count. With 3 zones, losing one removes a third of capacity, so the other two must carry everything. With 2 zones, each must carry the full load alone, which roughly doubles the fleet.
Worked example
The calculator's defaults, an illustrative stateless API:
- Design load: 3,000 RPS × 1.2 = 3,600 RPS.
- Normal: each instance should carry 400 × 0.70 = 280 RPS, so ceil(3,600 ÷ 280) = ceil(12.86) = 13 instances.
- Failure: survivors may run at 400 × 0.90 = 360 RPS, so 3,600 ÷ 360 = 10 survivors are needed.
- Zones: per zone = max(ceil(13 ÷ 3), ceil(10 ÷ 2)) = max(5, 5) = 5, so 15 instances, 5 in each of 3 zones.
- Check: at peak, 3,600 ÷ (15 × 400) = 60% utilization. With a zone down, 10 instances carry 3,600 RPS at 90%.
The same inputs give 13 with N+1 (13 normal already leaves 12 survivors, more than the 11 needed) and 13 with no redundancy. Zone resilience costs 2 extra instances here. With 2 zones instead of 3 it would cost far more: max(ceil(13 ÷ 2), ceil(10 ÷ 1)) = 10 per zone, 20 in total.
Getting per-instance RPS from a load test
The whole result scales with one input, the RPS a single instance sustains. Guessing it from CPU benchmarks or vendor numbers is how capacity plans go wrong. Measure it:
- Test one instance, or a known small number. Point the test at a single instance behind the load balancer, or at a fleet pinned to a fixed size with autoscaling off. Divide by the instance count.
- Use an arrival-rate test that steps up. For example, 100, 200, 300, 400, 500 RPS, a few minutes per step. A closed VU model slows down as the server slows, hiding the knee; open vs closed workload models explains why.
- Define "sustainable" with your SLO. The per-instance number is the highest step where p95 (or p99) latency and error rate still meet target, not the step where it falls over. If p95 must stay below 300 ms and it crosses at 450 RPS, use 400 or so, not 450.
- Use production-like data and dependencies. An instance in front of an empty database is faster than one in front of the real one.
In LoadTester this is an RPS-mode test with steps and a p95 threshold; the run comparison view makes it easy to repeat the measurement after each release and see whether per-instance capacity drifted. The capacity testing page covers the test design in more detail.
When instances do not add capacity linearly
The formula assumes 10 instances carry 10 times what one carries. That holds for stateless app servers until something they share runs out:
| Shared limit | Symptom as you add instances | What to check |
|---|---|---|
| Database CPU or connections | Throughput plateaus; p95 rises on every instance at once | Pool size × instances vs max_connections |
| Cache or session store | Latency spikes on cache-heavy endpoints | Cache server CPU, network and hot keys |
| Load balancer or NAT | Connection errors, resets, SNAT port exhaustion | LB capacity units, NAT port allocation |
| Downstream API rate limits | 429s rising with load | Partner quotas, rate limit behavior |
| Network egress | Throughput capped at a round Mbps value | Bandwidth at peak RPS |
So after sizing with the calculator, run one test at the full design load against the full fleet. If the fleet delivers less than instances × per-instance RPS, the gap is the shared bottleneck.
Autoscaling does not remove the need to size
Autoscaling sets the count for you, but the inputs here still matter. The minimum should cover the zone-failure case at your quietest expected peak, because new instances take minutes to start and warm up. The target utilization in the scaling policy is the normal-utilization input above. And the maximum must not exceed what shared dependencies can absorb. A spike that outruns scale-up is a separate problem; see autoscaling too slow and run a spike test.
Checklist
- Take the peak RPS from production metrics or the RPS calculator; add growth.
- Measure sustainable RPS per instance with a stepped arrival-rate test against your SLO.
- Choose normal and failure utilization targets and the redundancy model.
- Compute the instance count and per-zone split.
- Check shared limits: database connections, cache, load balancer, bandwidth.
- Run a full-fleet test at design load, then one with a zone's worth of instances removed.
FAQ
How do I calculate how many servers I need?
Divide your design peak RPS, including growth, by the RPS one instance sustains within your latency target multiplied by the target utilization, and round up. Then add redundancy: at least one extra instance for N+1, or enough per zone that the remaining zones carry the load if one fails.
What target CPU utilization should I plan for?
Many teams plan for 60 to 75 percent at normal peak, because queueing delay rises steeply as a server approaches full utilization. Allow a higher figure, such as 85 to 90 percent, only for the temporary state after a failure, and only if your load test showed latency still meets the SLO there.
How do I find the RPS one server can handle?
Run a stepped arrival-rate load test against a single instance or a fixed-size fleet with autoscaling off. The sustainable figure is the highest step where p95 latency and error rate still meet your target, not the step where the server fails.
What is the difference between N+1 and zone redundancy?
N+1 means one spare instance so a single instance failure does not overload the rest. Zone redundancy means the fleet survives losing a whole availability zone, so with three zones the remaining two must carry all traffic. Zone redundancy usually needs more instances.
Why doesn't doubling my servers double capacity?
Because instances share dependencies such as the database, cache, load balancer and downstream APIs. Once a shared component saturates, adding app servers adds little. Test the full fleet at design load to find that limit.