Observability & Operations
Capacity Planning
Capacity planning answers "will we have enough headroom before we need it" — using historical growth, seasonal peaks, and load testing to provision ahead of demand instead of reacting to an outage.
- Organic growth (steady user or traffic increase) and inorganic events (a marketing launch, a viral moment, a holiday sale) need different planning horizons — one is a trend line, the other is a spike to explicitly provision for
- Load testing against a production-like environment finds the actual breaking point of a system, not just its comfortable operating range
- Headroom targets — for example never running above 60-70% sustained utilization — leave room for both traffic spikes and losing capacity without an immediate crisis
- The bottleneck is rarely uniform across a system: CPU, memory, connection-pool limits, and downstream dependency quotas each have separate ceilings, and the lowest one wins
- Autoscaling handles gradual demand shifts well but reacts too slowly for sudden spikes — a scale-up event still takes minutes, so pre-provisioning ahead of a known event is still necessary
- Cost and capacity are the same conversation: over-provisioning "just in case" is a real, ongoing expense, not a free insurance policy
| Organic growth | Inorganic event | |
|---|---|---|
| Shape | steady trend line | sharp, time-boxed spike |
| Planning input | historical growth rate | known event date and expected multiplier |
| Response | autoscaling keeps pace | pre-provision ahead of time — autoscaling reacts too slowly |
int requiredInstances(double peakRps, double rpsPerInstance, double headroomFactor) {
// headroomFactor 1.4 targets roughly 70% sustained utilization at peak
return (int) Math.ceil(peakRps / rpsPerInstance * headroomFactor);
}