Designing a Capacity Forecasting System

A system design interview guide to predicting when you will run out of hardware — turning utilization telemetry into a demand forecast, a buffer policy, and a procurement order that lands before the wall does.

Student edition · start with the guarantee

Forecast unconstrained demand and purchase enough surviving capacity before lead time runs out.

Correctness contract: Forecasts state uncertainty/calibration, aggregation assumptions, and failure headroom. Procurement uses discrete capacity units and verified lead times.

Basic HTTP, databases, and programming are assumed. Specialized terms are explained below. Named products motivate the problem; this is an educational design, not a claim about their current internals. Capacity numbers are illustrative decimal payload estimates, not benchmarks. Add indexes, protocol overhead, replicas, headroom, and failure capacity before provisioning.

Fleets do not run out of capacity suddenly; they run out predictably, and the failure is almost always organizational rather than technical — nobody ordered the machines in time. Hardware has a long lead time: you cannot conjure a rack the day you need it, so you must see the shortfall coming weeks or months ahead and place the order early. A capacity forecasting system is the machine that makes that foresight routine. It ingests utilization telemetry, models future demand from trend, seasonality, and known growth, translates that demand into hardware and dollars, applies a headroom policy so you never run to the edge, and alerts — with enough runway — when a resource is projected to exhaust. This guide is infra-economics flavored: the output is not a dashboard, it is a purchase order placed at the right time.

Intuition first

Think of filling up a car before a long drive. You know how fast you burn fuel (the trend), that hills burn more (seasonality), and that the next gas station is 100 miles away (the lead time). You refuel when the tank will run low before the next station, not when the light comes on. Capacity forecasting does the same for servers, because new hardware can take months to arrive.

Contents

  1. Requirements & Scope
  2. Back-of-the-Envelope
  3. Key Definitions
  4. High-Level Architecture
  5. Modeling Demand
  6. Headroom & Exhaustion
  7. What-If & Procurement
  8. Bottlenecks & Tradeoffs
  9. Interview Walkthrough (45 Minutes)
  10. Common Mistakes
  11. Summary
  12. Check Yourself
  13. Key Terms
  14. Further Reading
  15. Concepts to understand first
  16. Worked example
  17. Runnable Python model

Concepts to understand first

Each definition includes a concrete example and the condition under which the mechanism is useful. You can read this guide without opening another guide.

Forecast percentiles and headroom

A forecast predicts future demand with uncertainty; P50 is a median, not necessarily a mean, and P90 is a quantile under the chosen model. Provision usable surviving capacity above a calibrated demand target.

Example. 6000 units growing 3% per month exceed 7500 usable units after log(7500/6000)/log(1.03)≈7.55 months. A 3.5-month procurement runway means order in about 4.05 months.

Limit. P90 does not mean a 90% chance of never exhausting capacity over the whole horizon. Per-service P90s do not generally add; model correlations, censored demand, lead time, and capacity granularity.

Failure domains and redundant capacity

A failure domain is a set of components vulnerable to one shared event: process, host, rack, zone, or region. Redundancy must separate domains and leave enough surviving capacity to carry peak demand.

Example. Five replicas placed 2/2/1 across three regions leave at least three after any one region fails. A 3/1/1 layout can lose its quorum with the largest region.

Limit. Independent-failure probability formulas are illustrative assumptions. Shared code/config, dependencies, routing, and control planes can fail all replicas together. N+1 machines does not imply tolerance of a whole zone.

SLIs, SLOs, and error budgets

An SLI measures a user-relevant outcome; an SLO sets its target over a window. For a success-ratio SLO, the allowed bad fraction is 1−SLO. An SLA is a contractual commitment that may use different definitions.

Example. 99.9% successful requests over 1 billion requests allows 1 million bad requests. A time-based 30-day availability target instead allows 43.2 unavailable minutes.

Limit. Request and time budgets are not interchangeable under variable traffic or partial failure. SLOs are not universally stricter than SLAs; choose both from their definitions and user needs.

Cardinality

The number of distinct identities a store must track. A metric series is its metric name plus the full label combination. The product of label-value counts is an upper bound when not every combination occurs.

Example. 100 hosts × 20 routes × 5 status codes can produce up to 10,000 series. Adding a unique request_id can make every request create a new series.

Limit. Hashing every ID to a distinct digest does not reduce cardinality or guarantee anonymity. Use bounded categories, explicit limits, or intentional fixed-bucket aggregation.

Backpressure and load shedding

Backpressure tells an upstream producer that the downstream stage cannot accept more work. Buffering delays that signal; shedding deliberately rejects or drops lower-priority work when a bound is reached.

Example. A sink accepts 100 events/s while input is 150/s. A 1000-event queue fills in 20 seconds. The system must then block, reject, or apply its documented drop policy.

Limit. A finite queue cannot absorb an infinite outage. Prioritized messages still need hard quotas, deadlines, and bounded client queues; otherwise an exemption can exhaust the system.

1. Requirements & Scope

The system’s job is to answer one question reliably: for each resource, when will demand exceed supply, and what should we buy to prevent it? Everything else serves that.

Questions to ask first

2. Back-of-the-Envelope

The numbers here are about horizons and lead times, because those set how far ahead the forecast must see and how early the alert must fire.

QuantityAssumptionResult
Telemetry cadenceutilization sampled every 1–5 minplenty of history; downsample to hourly/daily for modeling
Series countresource × service × region × HW typetens of thousands of forecastable series
Planning horizonforecast 2–4 quarters aheadneeds 1–2 years of history to learn seasonality
Procurement lead timeorder → racked & servingweeks to months — the number that matters most
Headroom bufferN+2 / keep ~20–30% freesurvive two failure domains lost (or one during maintenance), plus spikes
Alert runwayfire before exhaustion by≥ lead time + safety margin

The controlling number is procurement lead time. It defines the alert runway: if hardware takes eight weeks to arrive, a projected-exhaustion alert that fires four weeks out is useless. The whole system exists to convert a slow physical process (buying and racking machines) into a timely one by seeing far enough ahead.

Worked example: when do we order?

A cluster has 10,000 cores and uses 6,000 at peak. Policy keeps 25% free. Demand grows 3% per month, compounding. New hardware takes 3 months to arrive, and we want a 2-week safety margin.

QuantityReasoningResult
Usable capacity10,000 × (1 − 0.25)7,500 cores
Annual growth1.0312×1.43 per year
Months until usable is exhaustedln(7,500 / 6,000) ÷ ln(1.03)7.55 months
Order point7.55 − 3 lead − 0.5 marginorder within ~4 months
Demand in 12 months6,000 × 1.03128,555 cores
Capacity to cover 12 months8,555 ÷ 0.75, minus 10,000 ownedbuy ~1,406 cores

Growth compounds, so a straight-line guess (“180 cores a month”) gives 8.3 months and orders too late. Always use the compounding formula, and plan on the P90 forecast rather than this single growth rate.

3. Key Definitions

A shared vocabulary keeps the design honest, especially around what “capacity” and “headroom” actually mean.

TermMeaning
DemandForecasted resource need over time — what the workload will consume.
Supply / capacityProvisioned resource available — what the fleet can serve.
HeadroomFree capacity above current demand — the safety margin.
Buffer policyThe rule for how much headroom to keep (e.g. N+2, or 25% free).
Days-to-exhaustionTime until forecasted demand crosses the usable-capacity line.
Lead timeDelay from ordering hardware to it serving traffic.
Order pointThe moment you must order so hardware lands before the buffer is breached.

The core relationship: order point = exhaustion date − lead time − safety margin. The forecast’s only real purpose is to compute that date early enough to act on it.

4. High-Level Architecture

The system is a pipeline from raw telemetry to a procurement decision, with a planning loop hanging off the middle for what-if analysis.

Capacity forecasting pipeline: telemetry, ingest/ETL, metrics store, forecast engine, capacity planner, headroom policy, alerting, procurement/finance
Telemetry flows through ingest/ETL into a metrics store of history; the forecast engine projects demand; the capacity planner translates it to hardware and cost against a headroom policy; alerting watches for projected exhaustion; and results feed procurement and finance. What-if scenarios re-run the forecast.

5. Modeling Demand

Forecasting demand starts by recognizing that a utilization time series is not random — it is a few structured components plus noise. Decompose it, model each part, and recombine.

Trend, seasonality and growth feed a fitted model, which projects a forecast with a P50 line inside a P90 band
Demand decomposes into a long-run trend, repeating seasonality (daily, weekly, holiday), and known growth (launches, adoption). A model — Holt-Winters, ARIMA, or Prophet — fits these and projects forward with P50/P90 uncertainty bands.

Classic model choices: Holt-Winters (exponential smoothing with trend and seasonality) is simple and robust; ARIMA / SARIMA handles autocorrelation and seasonality with more rigor; Prophet is convenient for series with strong seasonality and holiday effects and tolerates gaps. The key output is not a single line but a distribution: forecast at P50 for the expected case and at P90 for planning, because you provision against a pessimistic percentile, not the average. You buy for the bad month, not the typical one.

for series in resources:
  hist   = store.history(series, window="2y")
  parts  = decompose(hist)                # trend + seasonality + residual
  model  = fit(parts, extra=known_events) # inject launches/migrations
  fc     = model.forecast(horizon,
                          quantiles=[0.5, 0.9]) # plan against P90
  publish(series, fc)
Common mistake: forecasting from utilization that hit the ceiling

Measured utilization can never go above 100%. When a service is throttled, queued or shedding load, its graph flattens at the cap, and the model learns that demand has stopped growing. The real demand is hidden. Forecast from request counts or queue depth as well, or mark saturated periods so the model does not trust them.

6. Headroom & Exhaustion

Plan against surviving capacity, not total installed capacity. N+1/N+2 conventionally denotes spare units, not automatically one/two whole failure domains. If one zone holds a third of servers, losing it removes that fraction; include peak load, maintenance, skew, and safe utilization on the remaining fleet.

Find when forecast demand crosses the usable threshold, then subtract procurement, installation, validation, and uncertainty margin. Handle current saturation, zero/negative growth, missing forecasts, and discrete purchase sizes. A 25% free-space buffer is a policy assumption, not proof all failures fit.

P50 is median; P90 is a forecast quantile, not guaranteed 90% survival over an entire horizon. Backtest coverage and model correlations. Do not add per-service percentiles blindly. Forecast uncensored demand from accepted/rejected work and backlog when observed utilization hit a ceiling.

7. What-If & Procurement

The forecast is a baseline; the value multiplies when planners can perturb it and when its output flows straight into the buying process.

Interview tip. The signal of a strong answer here is refusing to stop at “fit a time-series model.” Tie the forecast to the physical and financial reality: forecast at a pessimistic percentile (P90, not the mean), alert on the projection against a headroom buffer rather than current usage, and set the alert runway to at least the procurement lead time. The deliverable is a purchase order placed on time, not a pretty chart — say that explicitly.

8. Bottlenecks & Tradeoffs

Forecasting trades the cost of being wrong in one direction against the cost of being wrong in the other, and the design is mostly about choosing which error to prefer.

Worked example: compounding growth meets procurement delay

Current demand is 6000 units, capacity 10,000, reserved headroom 25%, monthly growth 3%.

Worked example, in orderCompute usable capacity: 10,000×0.75=7500 units. Headroom must separately include the defined failed-domain/maintenance scenario.. Find threshold crossing: log(7500/6000)/log(1.03)≈7.55 months to usable-capacity exhaustion under this deterministic growth assumption.. Subtract lead time: A 3-month lead plus 0.5-month installation margin leaves about 4.05 months until ordering. Already-saturated resources require immediate action, not a negative runway hidden in math.. Validate the forecast: Backtest quantile coverage, model correlations, and add known launches. A per-time P90 band is not a 90% no-exhaustion guarantee over the whole year.1Compute usable capacity2Find threshold crossing3Subtract lead time4Validate the forecast
Read top to bottom. The table below explains the state and guarantee at each step.
StepState, calculation, and reasoning
1. Compute usable capacity10,000×0.75=7500 units. Headroom must separately include the defined failed-domain/maintenance scenario.
2. Find threshold crossinglog(7500/6000)/log(1.03)≈7.55 months to usable-capacity exhaustion under this deterministic growth assumption.
3. Subtract lead timeA 3-month lead plus 0.5-month installation margin leaves about 4.05 months until ordering. Already-saturated resources require immediate action, not a negative runway hidden in math.
4. Validate the forecastBacktest quantile coverage, model correlations, and add known launches. A per-time P90 band is not a 90% no-exhaustion guarantee over the whole year.
Check your understanding: Can P90 forecasts from ten services simply be added?

Not generally. The percentile of a sum depends on dependence; model aggregate demand/correlation. P50 is a median, not always expected demand.

Run a small, testable model

Download concepts.py. It uses only the Python 3.10+ standard library. From the directory where you saved it, run:

python3 concepts.py capacity
python3 concepts.py test

The model calculates runway, uses ceiling for purchased units, and contrasts summed P90s with an independent normal aggregate.

The program contains deterministic assertions and failure traces. It is a learning model, not a production service: it does not implement network consensus, distributed durability, authentication, or third-party delivery. Read its contracts and try changing an input before extending it.

Primary references for these concepts

9. Interview Walkthrough (45 Minutes)

MinutesWhat you doWhat to say out loud
0–5ClarifyResources, granularity, lead time, cost of running out vs idle, who uses the output.
5–10EstimateSeries count, history needed, lead time sets the alert runway.
10–20ArchitectureTelemetry ingest → time-series store → forecasting jobs → plan store → alerts, dashboards, procurement.
20–30ModelTrend + seasonality + known events; P50 and P90; backtesting to measure error.
30–38Headroom and order pointBuffer policy, exhaustion date on P90, order point = exhaustion − lead time − margin. Do the worked math.
38–45TradeoffsOver- vs under-provisioning cost, per-series vs aggregate, saturated data, what-if scenarios.

10. Common Mistakes

MistakeWhy it hurtsDo this instead
Planning on the average (P50)Runs out in half the bad monthsPlan on P90 or higher; buffer for model error
Alerting on current usageBy the time it fires, hardware can’t arrive in timeAlert on the forecast crossing usable within the lead time
Linear growth for compounding demandOrders too lateFit growth rates; check against the compounding formula
Training on throttled, capped dataHides real demandUse request counts; flag saturated periods
Summing per-service P90sOver-buys shared capacityForecast the aggregate; model correlation
Never checking forecast accuracySilent drift; nobody trusts the planBacktest and track error (for example MAPE) per series

11. Summary

A capacity forecasting system converts slow physical procurement into timely action by seeing demand far enough ahead. Its deliverable is a well-timed order, and every part of the design serves the order point.

ConcernMechanism
What do we feed the model?Cleaned, downsampled utilization/growth telemetry with 1–2 years of history.
How do we model demand?Decompose into trend + seasonality + growth; fit Holt-Winters / ARIMA / Prophet.
What do we forecast against?A pessimistic percentile (P90) with uncertainty bands — provision for the bad case.
How much slack do we keep?A headroom buffer (N+2 or ~25% free) subtracted from provisioned capacity.
When do we alert?When the forecast (not current usage) is projected to breach the buffer within the runway.
How early must the alert be?At least procurement lead time plus a safety margin — the order point.
How do we plan changes?What-if scenarios re-run the forecast; output translates to hardware and cost.
How does it drive action?Integration with procurement and finance turns alerts into orders and capex plans.
The recurring theme: forecasting is an economics problem with a deadline. See demand far enough ahead, plan against a pessimistic percentile with a headroom buffer, and fire the alert a full lead time before the wall — because the only forecast that matters is the one that gets the hardware ordered in time.

12. Check Yourself

  1. Hardware takes 10 weeks to arrive and your alert fires 6 weeks before projected exhaustion. What is wrong?
    AnswerThe runway is shorter than the lead time. The alert must fire at least 10 weeks plus a margin before exhaustion, or the capacity arrives after you run out.
  2. Usage is 4,000 units, usable capacity is 5,000, and demand grows 2% per month. About how many months until exhaustion?
    Answerln(5,000 / 4,000) ÷ ln(1.02) ≈ 11.3 months.
  3. Why plan against P90 instead of P50?
    AnswerP50 is exceeded half the time. Running out is usually far more costly than a little idle capacity, so you plan for the pessimistic but plausible case.
  4. A service’s CPU graph has sat flat at 100% for two weeks. What does that tell the forecaster?
    AnswerDemand is being capped, so true demand is unknown and probably higher. Those points should not be trusted as demand; use request or queue metrics instead.
  5. What does N+2 protect you against?
    AnswerLosing two failure domains at peak, or more commonly one planned for maintenance plus one unplanned failure at the same time.
  6. How do you know your forecasting model is any good?
    AnswerBacktest it: train on data up to a past date, forecast the next months, and compare with what really happened. Track an error metric and check how often reality falls outside the P90 band.

13. Key Terms

Lead time
Time from ordering capacity to it serving traffic.
Headroom
Capacity kept free on purpose.
Usable capacity
Provisioned capacity minus the buffer.
Exhaustion date
When forecast demand crosses usable capacity.
Order point
Exhaustion date minus lead time minus margin.
Trend
Long-run direction of demand.
Seasonality
Cycles that repeat daily, weekly or yearly.
P50 / P90
Values that demand stays under 50% / 90% of the time.
Backtesting
Testing a model on past data it has not seen.
N+1 / N+2
Enough capacity to lose one / two failure domains.

14. Further Reading


⌂