Dark illustration of a capacity calendar, rising system curve, and server stacks.

scaling

Put Capacity Planning on the Product Calendar

A capacity calendar turns commercial forecasts into explicit engineering assumptions, review dates, and reversible choices.

A capacity incident often looks sudden only because the forecast never became an engineering date. The warning was already in the plan: an event or usage change that altered demand. By the time it reaches the pager, the team is choosing between delay, spend, and a reliability risk that had a quieter version weeks earlier.

Scaling work starts before a system is large. The useful unit is a calendar assumption, not a vague statement that traffic may grow. A CTO needs to see what commercial expectations ask of the system; a Staff or Principal engineer needs enough shape to test the path that will carry the load. Put both in the same planning habit, and uncertainty becomes visible while actions are still reversible.

Turn business events into demand shapes

A revenue forecast is not yet a capacity forecast. Translate the event into system behavior: which users arrive, what they do first, whether they act together, and which dependency receives the concentrated work. A renewal date might create a tight burst of reads and writes; a feature can shift the expensive operation entirely. The system cares about shape, not the business label.

Start with the path that matters to the customer, then follow its dependencies. Name the constrained resource, not just the service: a database connection pool, a queue consumer, a third-party limit, a hot partition, or the people who can safely change the component. This isn’t an instruction to predict every failure. It is a way to make the assumptions inspectable before they turn into an implicit promise.

A forecast earns its value when it changes a decision before urgency removes the cheaper options. The planning conversation should record what would disprove the assumption as well as what it expects. If a launch moves, a customer changes integration behavior, or adoption follows a different path, the calendar gives the team a place to revise rather than a document to defend.

The difference between common demand patterns is worth making explicit because they call for different preparations:

Planning dimension Stable growth Event spike Model or usage change
Demand shape Gradual, sustained increase in the normal path Concentrated load around a known deadline or release A new action or workflow changes which path is expensive
First question Which limit will be reached if the trend continues? Can the critical path absorb the burst without harming normal traffic? Which assumption about request cost, data access, or concurrency no longer holds?
Useful preparation Incremental capacity and a review point before the limit Queueing, admission rules, or a temporary operating plan Instrument the changed path and test the new bottleneck
Mistake to avoid Treating average load as proof of headroom Sizing permanently for a short-lived peak Adding resources to the old bottleneck after demand has moved

A stable trend and a spike can share the same graph while demanding opposite choices. Average traffic hides timing: an event can be harmless in aggregate and still overwhelm the one dependency everyone reaches at once. Conversely, treating every increase as a permanent plateau can lock the team into unnecessary operational work.

Put constraints and lead times on one calendar

A capacity calendar makes the work concrete. List each leading constraint beside its lead time: the decision, implementation, test, rollout, and rollback window required before it can help. Some changes are quick to reverse; others need data movement or coordination with another team. Calling them all “capacity” hides the scheduling problem.

The most useful calendar entries pair an expected event with an action and a review date. Separate the trigger from the response. “Demand may rise in Q3” is a concern; “review the queue backlog assumption two weeks before the planned import, then decide whether to add consumers” is an operating decision. The date is not a prediction of failure. It is the deadline for asking whether the current plan still deserves confidence.

flowchart LR
    F[Product and commercial forecast] --> A[Engineering assumptions]
    A --> C[Capacity calendar]
    C --> R[Scheduled review]
    R -->|Assumptions hold| K[Keep reversible preparation]
    R -->|Assumptions changed| D[Decide: optimise, add capacity, or limit demand]
    K --> C
    D --> C

The flow matters because it prevents forecasting from becoming a handoff. The calendar closes the loop between the people who know why demand may change and the people who know which system property will fail first. Neither group has to claim certainty; they need a shared time to compare the assumption with what is now true.

This is also where a planned capacity decision can expose commercial trade-offs early. A rushed choice rarely stays local: it can divert delivery work or worsen customer experience when the system is already under strain. The cost connection is familiar when a cloud bill scales faster than traffic; the same discipline asks whether spend, performance, and product timing are being treated as one decision or three unrelated surprises.

Keep sustained load separate from a deadline spike

The operational question is not simply whether more capacity is needed. Ask whether the load must be served now, forever, or only briefly. Sustained growth may justify a durable change to storage, compute, or data layout. A known spike may be safer to absorb through staged work, queueing, rate limits, or an agreed degraded mode. Those are different service promises, so they should not be hidden behind a single scaling ticket.

A deadline spike is especially easy to mishandle because it feels like proof of a long-term trend. Plan for the failure mode you can name. If concurrency is the concern, inspect the shared dependency it stresses; if work can wait, decide how it queues and how customers learn that it is delayed. This chooses where the system bends before it breaks somewhere less visible.

The safest capacity plan says what may degrade, for whom, and under which condition before that condition arrives. The trade-off is direct: planning takes attention away from the immediate roadmap, while skipping it preserves that focus until a deadline forces the same people into reactive delivery. Customers encounter the degraded behavior first; on-call engineers inherit the compressed decision window.

For a small system, this discipline should be lighter, not absent. A short list of assumptions is enough when there are few moving parts: the next commercial event, the request path it changes, the obvious dependency, and the date to look again. Complexity enters when the record grows stale or nobody owns the review, not when the first row appears on a calendar.

Use review dates to preserve reversible choices

A forecast should expire on purpose. Schedule the question, not just the work: what has changed since the last review, which assumption is weak, and which action is still cheap? Without that cadence, a planning document becomes either false certainty or a forgotten precaution. With it, the team can reduce or defer a change when demand has not appeared, instead of treating every forecast as an order.

When the review shows real pressure, choose the smallest intervention that buys time to learn. Optimisation and added capacity solve different problems. Add capacity when the path is understood, the constraint is genuine, and more of the same resource safely creates headroom. Optimise when the cost of each request or unit of work has changed, when one dependency is doing avoidable work, or when simply adding resources would amplify a design fault.

Neither option is automatically cheaper. Adding capacity can be the safer short-term move if it protects customers while the team measures the changed path; optimisation may lower recurring cost but can widen the change surface under pressure. The point is to decide while you can test and reverse the move, not to turn restraint into a virtue.

A scaling practice is useful only when it changes the next conversation. Treat the capacity calendar as a shared operating artifact, reviewed alongside product and commercial plans rather than published after the decision. It makes architecture legible to the business without pretending the forecast is certain. If your team needs help making those decisions visible, scaling work is the practice this discipline supports.

FAQ

How should we plan when the forecast is uncertain?

Write the uncertainty down as an assumption and give it a review date. Planning does not require a precise demand number; it requires a statement of what would change the decision, plus enough time to alter course if that statement turns out to be wrong.

Does this matter for a small system with few dependencies?

Yes, but the artifact should stay small. A lightweight calendar is often more valuable early because the team can still make changes without a long chain of approvals. The goal is to keep the next constraint visible, not to imitate the process of a larger organisation.

When should we add capacity instead of optimising first?

Add capacity when you understand the constraint and it safely buys headroom. Optimise first when the request path is doing avoidable work or the bottleneck has shifted, because more resources can make an inefficient pattern more expensive without making it predictable.

How often should the capacity calendar be reviewed?

Review it when the assumption could have changed, not by habit alone. Tie review dates to launches, commercial commitments, migrations, and other events that alter demand shape; add a regular check only when the system changes often enough that event-based reviews leave gaps.

Open the next product or commercial forecast and write four lines beside it today: the demand shape it creates, the dependency most likely to constrain it, the action that remains reversible, and the date someone will challenge the assumption.

← All notesFull archive →