Definition · Capacity and target utilisationThe capacity of a machine is the reciprocal of the scarce resource one request consumes. Its target utilisation ρ is the fraction of that capacity the design is willing to use, so usable capacity is capacity · ρ. The machine count is N = ⌈peak / (capacity · ρ)⌉.
Every term has to be a peak or none of them can be. The rate going in is the peak rate from “Peak to Average”, not the mean; a fleet sized from a mean rate is short for as long as the busy period lasts, and no amount of care about the ceiling rescues it.
cores per machine 8
cost of one request 40 ms of one core
capacity 8 · 1000 ms/s / 40 ms = 200 req/s
target utilisation ρ 60%
usable 200 · 0.6 = 120 req/s
peak rate 20 000 req/s
machines needed 20 000 / 120 = 500/3 = 166.67
N = ⌈500/3⌉ = 167
fleet capacity 167 · 200 = 33 400 req/s
the peak sits at 20 000 / 33 400 = 100/167 = 59.88%
spare 33 400 − 20 000 = 13 400 req/s
59.88% rather than 60% is the ceiling showing up in the answer: rounding 166.67 up to 167 bought two-thirds of a machine that nobody asked for, and the fleet is very slightly emptier than the target. That is the normal direction for this error to run, and it is the safe one.
Example · A checkout API at twenty thousand a secondEight cores, 40 ms of one core per request, 60% target. Each machine serves 200 requests a second and is allowed 120, so the fleet is 167 machines carrying 33 400 requests a second of raw capacity, 13 400 of which is deliberately unused. Sized at 100% the same peak gives 100 machines, and the sixty-seven machines between those two answers are the headroom, priced.
What the sixty-seven machines buy
Not insurance against the estimate being wrong. The target utilisation is a queueing decision: as utilisation approaches one, waiting time rises without bound, and a fleet run at 95% has a latency profile that no amount of extra patience fixes. 60% is a point on that curve, chosen so that the response time is tolerable and a machine can be lost without the rest going over the knee.
The uncertainty in the inputs is a separate and multiplicative thing. If the peak rate and the per-request cost are each known to a factor of two, the ranges from “Orders of Magnitude” put the fleet somewhere across a ÷4 … ×4 interval, and the headroom does not begin to cover that. Two different questions, two different answers, and conflating them produces a fleet that is neither adequately provisioned nor honestly estimated.
An integer is not a precise answer
167 looks like a hard number and is only as hard as its inputs. Halve the per-request cost in the lab and the same peak and target give 84; double it and they give 334. Nothing about the ceiling makes 167 more certain than the 40 ms it came from — the ceiling removes the fractional part, not the range. The honest report names the fleet and the assumption that moves it most, which here is the cost of a request.
One constraint, and the case with two
This is the one-constraint version: the fleet is sized by request throughput and by nothing else. Real fleets are often held up by a second constraint at the same time — a data volume that will not fit, a connection count, a per-node write rate — and then the answer is the larger of the two ceilings rather than either one. “How Many Shards”, on Partitioning and Load Balancing, is that lesson: the same ceiling computed twice and a maximum taken. Doing the one-constraint case first is worth it, because the trap there is always to compute one ceiling and stop.