# Capacity Plan: [Service or platform name] [Planning period]

> Complete capacity plan for one or more production services: demand
> forecast, current utilisation, headroom policy, resource models,
> bottlenecks, scaling plan, procurement, cost and risks. Based on
> common site reliability engineering practice. Replace every
> `[bracketed]` value and every row marked *Example*.

<!--
Guidance: How to use this template
- Start from measured data. Pull at least 90 days of peak utilisation
  per resource before forecasting anything.
- Plan for peaks, not averages. A service at 40% average CPU can still
  saturate every Monday at 09:00.
- Express every model as a formula with named inputs, so reviewers can
  change one assumption and see the effect.
- Tie each scaling action to a trigger and an owner; a forecast with no
  action attached is only a chart.
-->

## Document control

<!-- Guidance: Capacity plans are revisited every period; make the period and the data cut-off obvious. -->

| Field | Value |
|---|---|
| Document ID | [CAP-SERVICE-2026Q4] |
| Services covered | [Service names or "see 2"] |
| Planning period | [YYYY-MM-DD to YYYY-MM-DD] |
| Data cut-off | YYYY-MM-DD |
| Version | [0.1] |
| Status | [Draft / In review / Approved / Superseded] |
| Owner | [@capacity-owner] |
| Classification | [Internal] |
| Related documents | [SLO document], [System design], [Budget], [Previous capacity plan] |

### Approvals

| Role | Name | Decision | Date |
|---|---|---|---|
| Service owner | [@name] | [Approved / Changes requested] | YYYY-MM-DD |
| SRE lead | [@name] | [Decision] | YYYY-MM-DD |
| Finance / FinOps | [@name] | [Decision] | YYYY-MM-DD |
| Product lead | [@name] | [Decision] | YYYY-MM-DD |

## Revision history

<!-- Guidance: Note forecast changes and why, so the next plan can measure forecast accuracy. -->

| Version | Date | Author | Change summary |
|---|---|---|---|
| 0.1 | YYYY-MM-DD | [@name] | Initial draft from Q3 telemetry |
| 0.2 | YYYY-MM-DD | [@name] | *Example:* Raised growth rate from 4% to 6% per month after marketing launch confirmed |
| 1.0 | YYYY-MM-DD | [@name] | *Example:* Approved with budget for 12 additional nodes |

## Contents

<!-- Guidance: Keep aligned with the headings below. -->

1. [Summary](#1-summary)
2. [Services in scope](#2-services-in-scope)
3. [Demand forecast](#3-demand-forecast)
4. [Current utilisation](#4-current-utilisation)
5. [Headroom policy](#5-headroom-policy)
6. [Resource models per tier](#6-resource-models-per-tier)
7. [Bottleneck analysis](#7-bottleneck-analysis)
8. [Scaling plan](#8-scaling-plan)
9. [Procurement and lead times](#9-procurement-and-lead-times)
10. [Cost projection](#10-cost-projection)
11. [Risks and assumptions](#11-risks-and-assumptions)
12. [Review cadence and accuracy tracking](#12-review-cadence-and-accuracy-tracking)
13. [Appendices](#13-appendices)

## 1. Summary

<!-- Guidance: Half a page for a decision maker: what demand is coming, when we run out, what we will do and what it costs. -->

[Summarise in four to six sentences. Example: "Peak request rate is
forecast to grow from 4,200 to 7,500 requests per second by the end of
Q2. At current efficiency the database tier exhausts its CPU headroom in
week 14. We propose moving to a larger instance class in week 10 and
adding two read replicas, at an incremental cost of [amount] per month.
All other tiers have headroom until at least Q3."]

### 1.1 Key decisions requested

| ID | Decision | Recommended option | Deadline | Section |
|---|---|---|---|---|
| CD-01 | *Example:* Approve database instance upgrade | Upgrade in week 10 | YYYY-MM-DD | 8.2 |
| CD-02 | *Example:* Commit to 1-year reservation for web tier | Commit 60% of baseline | YYYY-MM-DD | 10.2 |
| [CD-nn] | [Decision] | [Option] | YYYY-MM-DD | [Section] |

## 2. Services in scope

<!-- Guidance: List every service and shared dependency included, with the unit of demand that drives it. Shared infrastructure without an owner is where capacity surprises hide. -->

| Service | Owner | Demand driver | Unit | SLO reference | Notes |
|---|---|---|---|---|---|
| *Example:* Checkout API | [@team] | Orders placed | requests/s | SLO-CHK-01 | Peak in evening hours |
| *Example:* Orders database | [@team] | Writes from checkout, reads from API | transactions/s | SLO-DB-01 | Single primary |
| *Example:* Event stream | [@team] | Order and click events | messages/s | SLO-EVT-01 | Shared with analytics |
| [Service] | [@team] | [Driver] | [Unit] | [SLO-ID] | [Notes] |

Out of scope: [list services excluded and the reason, for example "batch
reporting cluster, covered by the data platform plan"].

## 3. Demand forecast

<!-- Guidance: State the model, its inputs and its uncertainty. Combine organic growth with known events such as launches, campaigns and seasonality. -->

### 3.1 Baseline demand

| Metric | Value | Measured over | Source |
|---|---|---|---|
| Peak requests per second (p99 of daily peaks) | *Example:* 4,200 | Last 90 days | [Dashboard link] |
| Average requests per second | *Example:* 1,350 | Last 90 days | [Dashboard link] |
| Peak-to-average ratio | *Example:* 3.1 | Last 90 days | Derived |
| Active users (monthly) | *Example:* 1.8 M | Last full month | [Product analytics] |
| [Metric] | [Value] | [Window] | [Source] |

### 3.2 Growth model

Organic growth is modelled as compound growth per period:

$$
D_t = D_0 \, (1 + g)^t
$$

where $D_0$ is baseline peak demand, $g$ is growth per period and $t$
is the number of periods. *Example:* with $D_0 = 4{,}200$ req/s and
$g = 0.05$ per month, demand after 12 months is
$4{,}200 \times 1.05^{12} \approx 7{,}540$ req/s.

Known events are added as multiplicative uplifts on the affected
periods:

$$
D_t^{\text{peak}} = D_0 \, (1 + g)^t \times \prod_{e \in E_t} (1 + u_e)
$$

where $u_e$ is the expected uplift of event $e$ active in period $t$.

### 3.3 Planned events

| Event | Period | Expected uplift $u_e$ | Confidence | Source |
|---|---|---|---|---|
| *Example:* Annual sale | Week 47 | +120% for 3 days | Medium | Marketing calendar |
| *Example:* New market launch | Month 4 onwards | +15% permanent | Low | Product roadmap |
| [Event] | [Period] | [Uplift] | [High / Medium / Low] | [Source] |

### 3.4 Forecast table

| Period | Organic demand | Event uplift | Planned peak | Low scenario | High scenario |
|---|---|---|---|---|---|
| *Example:* Month 1 | 4,410 | 0% | 4,410 | 4,300 | 4,550 |
| *Example:* Month 6 | 5,630 | 15% | 6,470 | 5,900 | 7,200 |
| *Example:* Month 12 | 7,540 | 15% | 8,670 | 7,400 | 10,100 |
| [Period] | [Value] | [%] | [Value] | [Value] | [Value] |

[Explain how the low and high scenarios were produced, for example by
varying $g$ between 3% and 7% per month.]

## 4. Current utilisation

<!-- Guidance: Record peak utilisation per resource and tier, not averages. Note the limit each value is measured against. -->

| Tier | Resource | Provisioned | Peak used | Peak utilisation | Limit type | Trend (90 days) |
|---|---|---|---|---|---|---|
| *Example:* Web | CPU | 40 vCPU | 22 vCPU | 55% | Soft (autoscale) | +4% per month |
| *Example:* Web | Memory | 160 GiB | 70 GiB | 44% | Hard | Flat |
| *Example:* Database | CPU | 32 vCPU | 22 vCPU | 69% | Hard (single primary) | +6% per month |
| *Example:* Database | Storage | 2 TiB | 1.3 TiB | 65% | Hard | +45 GiB per month |
| *Example:* Database | Connections | 1,000 | 610 | 61% | Hard | +3% per month |
| *Example:* Event stream | Partition throughput | 48 MB/s | 19 MB/s | 40% | Soft | +5% per month |
| [Tier] | [Resource] | [Amount] | [Amount] | [%] | [Hard / Soft] | [Trend] |

Quotas and provider limits that apply: [list account quotas, API rate
limits and licence caps with their current usage].

## 5. Headroom policy

<!-- Guidance: Headroom is the spare capacity you keep for spikes, failures and the time it takes to add capacity. Make it explicit per tier. -->

Each tier keeps enough spare capacity to absorb a traffic spike and the
loss of one failure domain while new capacity is added. The maximum
planned utilisation $U_{\max}$ for a tier is:

$$
U_{\max} = \frac{N - F}{N} \times \frac{1}{1 + s}
$$

where $N$ is the number of failure domains (for example zones), $F$ the
number of domains that may fail at once, and $s$ the spike allowance.
*Example:* $N = 3$, $F = 1$, $s = 0.2$ gives
$U_{\max} = \tfrac{2}{3} \times \tfrac{1}{1.2} \approx 56\%$.

| Tier | Failure domains $N$ | Tolerated failures $F$ | Spike allowance $s$ | $U_{\max}$ | Action threshold |
|---|---|---|---|---|---|
| *Example:* Web | 3 zones | 1 | 20% | 56% | Scale at 50% sustained 15 min |
| *Example:* Database | 1 primary | 0 (failover to replica) | 30% | 77% | Plan upgrade at 65% peak |
| [Tier] | [N] | [F] | [s] | [%] | [Threshold] |

## 6. Resource models per tier

<!-- Guidance: Convert demand into resources. A good model is one line per resource with a measured per-unit cost, validated by a load test. -->

### 6.1 Web tier

Instances required at peak:

$$
n_{\text{web}} = \left\lceil \frac{D^{\text{peak}}}{r_{\text{inst}} \times U_{\max}} \right\rceil
$$

where $r_{\text{inst}}$ is the measured sustainable throughput of one
instance. *Example:* $r_{\text{inst}} = 350$ req/s (load test LT-12),
$D^{\text{peak}} = 8{,}670$ req/s, $U_{\max} = 0.56$ gives
$n_{\text{web}} = \lceil 44.2 \rceil = 45$ instances.

### 6.2 Database tier

| Resource | Per-unit cost | Model | Value at month 12 peak |
|---|---|---|---|
| CPU | *Example:* 11 ms CPU per transaction (measured: 22 vCPU at 2,000 tps) | $\text{vCPU} = D \times c / 1000 / U_{\max}$ | 4,100 tps x 11 / 1000 / 0.77 = 59 vCPU, so the 64 vCPU class is needed |
| Storage | *Example:* 45 GiB growth per month | $S_t = S_0 + 45\,t$ | 1.3 + 0.54 = 1.84 TiB |
| Connections | *Example:* 0.145 per req/s | $C = 0.145 \times D$ | 1,257 (exceeds 1,000 limit) |
| [Resource] | [Cost] | [Model] | [Value] |

### 6.3 [Other tier]

[Repeat for each tier: caches, queues, storage, third-party APIs and
licences. Note which models were validated by a load test and when.]

## 7. Bottleneck analysis

<!-- Guidance: Find the first resource to run out. Rank by time to exhaustion, and check hard limits that cannot be scaled quickly. -->

Time to exhaustion for a resource growing at rate $g$ per period from
utilisation $U_0$ to threshold $U_{\max}$:

$$
t_{\text{exhaust}} = \frac{\ln(U_{\max} / U_0)}{\ln(1 + g)}
$$

*Example:* database CPU at $U_0 = 0.69$, $U_{\max} = 0.77$, $g = 0.06$
per month gives $t \approx 1.9$ months.

| Rank | Resource | Current | Threshold | Time to exhaustion | Scalable how | Lead time |
|---|---|---|---|---|---|---|
| 1 | *Example:* Database CPU | 69% | 77% | 1.9 months | Vertical only | 2 weeks |
| 2 | *Example:* Database connections | 61% | 90% | 13.2 months | Pooler | 1 week |
| 3 | *Example:* Web CPU | 55% | 56% | Now at threshold | Horizontal, automatic | Minutes |
| [n] | [Resource] | [%] | [%] | [Time] | [How] | [Time] |

The dependency diagram shows where saturation in one tier propagates.

```mermaid
flowchart LR
  U["Users"] --> LB["Load balancer"]
  LB --> W["Web tier (autoscaled)"]
  W --> C["Cache"]
  W --> DB["Orders database (bottleneck 1)"]
  W --> Q["Event stream"]
  Q --> A["Analytics consumers"]
```

## 8. Scaling plan

<!-- Guidance: For each bottleneck, state the action, the trigger that starts it, who owns it and when it must be complete. Prefer horizontal scaling where the design allows. -->

### 8.1 Automatic scaling

| Tier | Mechanism | Metric | Scale-out trigger | Scale-in trigger | Min / max |
|---|---|---|---|---|---|
| *Example:* Web | Horizontal autoscaler | CPU | > 50% for 5 min | < 30% for 20 min | 12 / 60 |
| *Example:* Event consumers | Queue-based scaler | Consumer lag | > 10,000 messages | < 1,000 messages | 4 / 32 |
| [Tier] | [Mechanism] | [Metric] | [Trigger] | [Trigger] | [Min / Max] |

### 8.2 Planned scaling actions

| ID | Action | Type | Trigger or date | Owner | Complete by | Status |
|---|---|---|---|---|---|---|
| SC-01 | *Example:* Move database to next instance class (32 to 64 vCPU) | Vertical | Week 10 or CPU peak > 72% | [@name] | YYYY-MM-DD | [Planned] |
| SC-02 | *Example:* Add connection pooler in front of database | Architectural | Before connections > 800 | [@name] | YYYY-MM-DD | [Planned] |
| SC-03 | *Example:* Raise web autoscaler max from 60 to 80 | Horizontal | Before annual sale | [@name] | YYYY-MM-DD | [Planned] |
| [SC-nn] | [Action] | [Horizontal / Vertical / Architectural] | [Trigger] | [@name] | YYYY-MM-DD | [Status] |

### 8.3 Efficiency improvements

[List optimisations that reduce per-unit cost, with the expected effect
on the models in section 6. Example: "Caching product lookups is expected
to cut database reads by 35%, reducing CPU per transaction from 11 ms
to 8 ms."]

## 9. Procurement and lead times

<!-- Guidance: Capacity that takes weeks to obtain must be ordered before the trigger fires. Work back from the exhaustion date. -->

| Item | Quantity | Supplier / provider | Lead time | Order by | Approval needed | Status |
|---|---|---|---|---|---|---|
| *Example:* Regional vCPU quota increase | +200 vCPU | [Cloud provider] | 5 working days | YYYY-MM-DD | SRE lead | [Requested] |
| *Example:* Database licence tier upgrade | 1 | [Vendor] | 3 weeks | YYYY-MM-DD | Finance | [Not started] |
| *Example:* On-premises storage shelf | 2 | [Vendor] | 8 weeks | YYYY-MM-DD | CTO | [Not started] |
| [Item] | [Qty] | [Supplier] | [Time] | YYYY-MM-DD | [Role] | [Status] |

The latest order date for an item is:

$$
t_{\text{order}} = t_{\text{exhaust}} - (L + B)
$$

where $L$ is the lead time and $B$ a safety buffer for installation and
testing.

## 10. Cost projection

<!-- Guidance: Show cost per period for the planned capacity, and the cost per unit of demand so efficiency can be tracked. -->

### 10.1 Projected cost

| Period | Web | Database | Event stream | Storage | Total | Cost per 1,000 requests |
|---|---|---|---|---|---|---|
| *Example:* Current | [Amount] | [Amount] | [Amount] | [Amount] | [Amount] | [Amount] |
| *Example:* Month 6 | [Amount] | [Amount] | [Amount] | [Amount] | [Amount] | [Amount] |
| *Example:* Month 12 | [Amount] | [Amount] | [Amount] | [Amount] | [Amount] | [Amount] |

Unit cost is computed as:

$$
c_{\text{unit}} = \frac{\text{Total cost for period}}{\text{Requests served in period} / 1000}
$$

### 10.2 Commitments and purchasing options

[Describe which baseline capacity will be covered by reservations or
committed-use discounts, and which remains on demand. Example: "Commit
60% of the month-6 web baseline for one year; keep spikes on demand."]

## 11. Risks and assumptions

<!-- Guidance: List what could make the forecast wrong and what you will do about it. -->

### 11.1 Assumptions

- *Example:* Request mix stays within 5% of the current read/write ratio.
- *Example:* No change in client retry behaviour.
- [Assumption]

### 11.2 Risks

| ID | Risk | Likelihood | Impact | Mitigation | Owner |
|---|---|---|---|---|---|
| CR-01 | *Example:* Growth exceeds high scenario after viral campaign | Low | High | Autoscaler max raised; database upgrade pre-approved | [@name] |
| CR-02 | *Example:* Provider has no capacity for larger instance class in region | Medium | High | Reserve capacity in advance; test alternate class | [@name] |
| CR-03 | *Example:* New feature doubles per-request database cost | Medium | Medium | Capacity review in design checklist | [@name] |
| [CR-nn] | [Risk] | [L / M / H] | [L / M / H] | [Mitigation] | [@name] |

## 12. Review cadence and accuracy tracking

<!-- Guidance: A capacity plan is a living document. Compare forecast to actual each period and adjust the model. -->

| Review | Frequency | Participants | Inputs | Output |
|---|---|---|---|---|
| Utilisation check | Weekly | SRE on duty | Dashboards | Exceptions raised |
| Plan review | Monthly | Service owners, SRE, FinOps | Forecast vs actual | Updated actions in 8.2 |
| Full replan | Quarterly | All approvers | New telemetry, roadmap | New version of this document |

Forecast error for each period is tracked as:

$$
\text{Error}_t = \frac{D_t^{\text{actual}} - D_t^{\text{forecast}}}{D_t^{\text{forecast}}}
$$

| Period | Forecast peak | Actual peak | Error | Comment |
|---|---|---|---|---|
| *Example:* Month 1 | 4,410 | 4,620 | +4.8% | Campaign started early |
| [Period] | [Value] | [Value] | [%] | [Comment] |

## 13. Appendices

<!-- Guidance: Keep raw data references, load test evidence and terminology here. -->

### 13.1 Load test evidence

| Test ID | Date | Tier | Result | Report |
|---|---|---|---|---|
| LT-12 | YYYY-MM-DD | *Example:* Web | 350 req/s per instance at p99 < 250 ms | [Link] |
| [LT-nn] | YYYY-MM-DD | [Tier] | [Result] | [Link] |

### 13.2 Data sources

[List the dashboards, queries and exports used, with time ranges, so the
next planner can reproduce the numbers.]

### 13.3 Glossary

| Term | Meaning |
|---|---|
| Headroom | Spare capacity kept above planned peak |
| Failure domain | A unit that can fail independently, such as a zone or rack |
| Time to exhaustion | Time until a resource reaches its threshold at the forecast growth rate |
| Unit cost | Cost divided by units of demand served |

## Standard and licence note

Based on common site reliability engineering and IT capacity management
practice for demand forecasting, headroom and scaling plans. Original
text written for this collection; example numbers are illustrative.
Template licence: MIT.
