Capacity Plan Template

What it is

A capacity plan is a forward-looking document that analyzes a service's current resource consumption, projects how that consumption will grow over time, and recommends infrastructure changes needed to sustain performance and availability through the projected growth period. It translates business growth forecasts — user growth, transaction volume, data volume — into concrete infrastructure requirements before those requirements become urgent.

Capacity planning sits at the intersection of performance engineering, financial planning, and reliability. It requires understanding a service's resource utilization profile (which resources are the binding constraints), its scaling behavior (which resources scale linearly with load and which scale non-linearly or require re-architecture at certain thresholds), and the procurement lead times and costs associated with adding capacity. Done well, it prevents capacity-related incidents and ensures that engineering and finance teams are aligned on infrastructure cost trajectories.

In cloud environments, capacity planning takes a different shape than in on-premises data centers. Auto-scaling handles many routine capacity needs automatically, shifting the focus from "how many servers do we need?" to "what are our scaling thresholds, what are our cost projections, and are there architectural bottlenecks that auto-scaling cannot address?" Database capacity, network egress, and managed service quotas are often the binding constraints that require explicit planning in cloud architectures.

Why it exists

Capacity-related failures are among the most preventable and most embarrassing classes of production incidents. A service that performs flawlessly at current load but has a known architectural bottleneck at 2x load will fail predictably if that bottleneck is not addressed before growth arrives. Yet in many engineering organizations, capacity planning is reactive — teams become aware of capacity constraints only when they materialize as incidents, at which point remediating them under production pressure is expensive, stressful, and often requires emergency budget approvals.

Capacity plans provide engineering leadership and finance with the information they need to make infrastructure investment decisions at the right time. Infrastructure procurement — whether requesting reserved instances, negotiating cloud contracts, or scheduling re-architecture work — requires lead time. A capacity plan written six months before a projected constraint is actionable; the same analysis written the week before a business event (product launch, peak season, marketing campaign) often cannot produce results in time.

For regulated industries and enterprise sales, capacity plans also serve as evidence that the organization has a systematic approach to ensuring service availability. Enterprise customers performing vendor due diligence ask about capacity management practices; a documented capacity planning process is a meaningful differentiator from competitors who manage capacity ad hoc.

When to use

  • Annually, as part of the engineering budget cycle, to ensure infrastructure investment aligns with the projected growth in the following fiscal year.
  • Before a major business event — product launch, geographic expansion, marketing campaign, peak season — where a known traffic surge will test the service's capacity.
  • When a monitoring alert or performance review reveals that a resource is approaching its saturation point (typically 60–70% sustained utilization).
  • When significant architectural changes are planned that will materially change the service's resource utilization profile.
  • When cost anomalies in cloud spend suggest inefficient resource allocation that warrants a formal review of capacity sizing.

When NOT to use

  • For services with negligible load or internal tools where infrastructure costs are trivial and resource constraints are not a practical concern.
  • As a substitute for proper auto-scaling configuration — if auto-scaling is properly configured and the service has no bottlenecks that auto-scaling cannot address, a formal capacity plan may add overhead without value.
  • When projections are so uncertain that the plan would be based on guesses rather than data — use load testing and profiling to establish a performance baseline before projecting.
  • For one-off batch jobs or short-lived workloads where permanent capacity changes are not warranted.

Template

# Capacity Plan: [Service Name]

**Service:** [Service name]
**Author(s):** [Name(s)]
**Reviewers:** [Name (Engineering Lead)], [Name (Finance / FinOps)]
**Status:** Draft | Approved | Superseded
**Plan period:** [YYYY-MM] to [YYYY-MM]  
**Created:** [YYYY-MM-DD]
**Next review:** [YYYY-MM-DD]
**Related SLO document:** [Link]
**Related design doc:** [Link if architectural changes are recommended]

---

## Executive Summary

[Service name] currently serves [N] requests/day with [X]% average CPU utilization
across [N] instances. Based on [Y]% projected user growth over the next 12 months,
the primary bottleneck is [resource type], which will reach saturation by [YYYY-MM]
without intervention. We recommend [brief action] at an estimated additional monthly
cost of $[X], which is required by [YYYY-MM].

---

## Service Overview

**Description:** [What the service does and who uses it]
**Architecture:** [Brief description — e.g., "Stateless HTTP API, 4 pods, PostgreSQL primary + 2 read replicas, Redis cache, Kafka consumer group (2 workers)"]
**Environments in scope:** Production (this plan covers production only)
**Measurement period:** [Start date] to [End date] — all current usage metrics are averages over this period

---

## Current Usage Metrics

### Traffic
| Metric | Current Value | Peak (last 90 days) | Measurement |
|--------|--------------|---------------------|-------------|
| Requests/day (avg) | [N] | [N] | [Data source / query] |
| Requests/second (avg) | [N] | [N peak RPS] | [Data source] |
| Requests/second (p99 peak) | [N] | — | [Data source] |
| Active users (DAU) | [N] | [N] | [Data source] |

### Compute
| Resource | Instance type | Count | Avg utilization | Peak utilization |
|----------|--------------|-------|----------------|-----------------|
| API pods | [e.g., m5.xlarge] | [N] | [X]% CPU, [Y]% memory | [X]% CPU, [Y]% memory |
| Worker pods | [instance type] | [N] | [X]% CPU | [X]% CPU |

**CPU profile:** [Is the service CPU-bound, I/O-bound, or memory-bound? What is the typical CPU per request?]

### Database
| Resource | Type | Size | Avg CPU | Peak CPU | Storage used | Storage growth/month |
|----------|------|------|---------|----------|-------------|---------------------|
| PostgreSQL primary | [instance type] | [Xvcore/YRAM] | [Z]% | [Z]% | [N GB] | [N GB/month] |
| PostgreSQL replica | [instance type] | [Xvcore/YRAM] | [Z]% | [Z]% | — | — |
| Redis | [instance type/cluster] | [N nodes] | [Z]% | [Z]% | [N GB] | [N GB/month] |

**DB connection pool:** Max connections: [N], Current peak active: [N] ([X]% utilized)
**Slow queries (> 100ms):** [N per day on average — link to slow query log or dashboard]

### Storage
| Store | Current size | Growth rate | Projected size (12 months) |
|-------|-------------|-------------|--------------------------|
| PostgreSQL data | [N GB] | [N GB/month] | [N GB] |
| Object storage (S3/GCS) | [N GB/TB] | [N GB/month] | [N GB/TB] |
| Kafka (log retention) | [N GB] | [N GB/day] | [N GB] |
| Backup storage | [N GB] | — | [N GB] |

### Network
| Flow | Current bandwidth | Peak | Notes |
|------|------------------|------|-------|
| Inbound | [N GB/day] | [N GB/hour peak] | CDN fronted: yes/no |
| Egress | [N GB/day] | — | [Cost: $X/month] |
| Internal service-to-service | [N GB/day] | — | Same-region: free/charged |

---

## Growth Projections

### Business Growth Assumptions


| Assumption | Value | Source |
|------------|-------|--------|
| User growth rate (YoY) | [X]% | [Product roadmap / sales forecast] |
| Transaction volume growth (YoY) | [X]% | [Finance model] |
| Peak traffic multiplier (seasonal) | [X]x | [Historical data] |
| New regions to launch | [N regions] | [Product roadmap] |
| Major feature launches | [List] | [Engineering roadmap] |

### Projected Load — 6 and 12 Month Horizons

| Metric | Now | +6 months | +12 months | Basis |
|--------|-----|-----------|------------|-------|
| Requests/day | [N] | [N] | [N] | [X]% monthly growth |
| Peak RPS | [N] | [N] | [N] | [assumption] |
| Active users (DAU) | [N] | [N] | [N] | [source] |
| Data stored (DB) | [N GB] | [N GB] | [N GB] | [X GB/month growth] |
| Egress | [N GB/day] | [N GB/day] | [N GB/day] | [assumption] |

---

## Resource Requirements

### Compute

**Current headroom:** At projected +12 month load, API pod CPU utilization reaches
[X]% (headroom exhausted at ~[X+N]% sustained — estimated [YYYY-MM]).

| Scenario | Instance type | Pod count | Notes |
|----------|--------------|-----------|-------|
| Current (baseline) | [type] | [N] | [X]% avg CPU |
| +6 months (no change) | [type] | [N] | [X]% avg CPU (projected) |
| +12 months (no change) | [type] | [N] | [X]% avg CPU — OVER LIMIT |
| +12 months (recommended) | [type] | [N+K] | [X]% avg CPU |

**Auto-scaling:** Min [N], Max [N], Target CPU [X]%. At +12m projected peak, max replicas
would be reached. Recommend increasing max to [N+K] — no cost impact until peak is sustained.

---

### Database

**PostgreSQL primary CPU:** Currently at [X]% avg. Projects to [Y]% by +12m — approaching
the [Z]% threshold where query latency degradation begins. **Action required.**

**Storage:** At [N GB/month] growth, storage will reach the [N GB] provisioned limit
in [N months]. Resize required by [YYYY-MM].

**Connection pool:** Currently at [X]% of the [N connection] limit. No immediate action,
but monitor monthly.

| Resource | Current | +6 months | +12 months | Action |
|----------|---------|-----------|------------|--------|
| Primary CPU | [X]% | [Y]% | [Z]% | Vertical scaling to [type] by [YYYY-MM] |
| Primary storage | [N GB] | [N GB] | [N GB] | Resize to [N+X GB] by [YYYY-MM] |
| Read replicas | [N] | [N] | [N+1] | Add replica for read scaling by [YYYY-MM] |

---

### Storage

| Store | Growth projection | Action required | By |
|-------|------------------|----------------|-----|
| PostgreSQL | +[X GB/month] | Resize to [N GB] | [YYYY-MM] |
| S3/GCS | +[X GB/month] | Storage is elastic — no action; review cost | [YYYY-MM] |
| Kafka retention | +[X GB/day] | Reduce retention from [N days] to [N-K days] OR add capacity | [YYYY-MM] |

---

### Network

**Egress cost:** Current $[X]/month. At +12m projected growth: $[X+Y]/month (+[Z]%).
**Recommendation:** Evaluate CDN caching for static assets — estimated 30–40% egress reduction.

---

## Scaling Thresholds



| Resource | Monitor | Warning threshold | Critical threshold | Action |
|----------|---------|-------------------|--------------------|--------|
| API pod CPU (sustained > 5m) | Prometheus | 60% | 80% | Scale out (auto-scaling) / alert |
| API pod memory | Prometheus | 75% | 90% | Investigate memory leak / scale |
| DB primary CPU | CloudWatch | 60% | 75% | Vertical scale / query optimize |
| DB connections | Prometheus | 70% | 85% | Add read replica / pool increase |
| DB storage | CloudWatch | 70% | 85% | Resize storage volume |
| Kafka consumer lag | Prometheus | 10k messages | 100k messages | Add workers |

---

## Cost Projections

### Current Monthly Infrastructure Cost

| Component | Monthly cost |
|-----------|-------------|
| Compute (API + workers) | $[X] |
| Database (primary + replicas) | $[X] |
| Cache (Redis) | $[X] |
| Storage (S3/GCS + backups) | $[X] |
| Network egress | $[X] |
| Managed services (Kafka, etc.) | $[X] |
| **Total current** | **$[TOTAL]** |

### Projected Monthly Cost

| Scenario | +6 months | +12 months | Change vs now |
|----------|-----------|------------|---------------|
| No action (grow into existing infra) | $[X] | $[X] | +[Y]% |
| With recommended changes | $[X] | $[X] | +[Y]% |

**Annual infrastructure cost (with recommendations):** $[X] (vs $[Y] current annualized)

---

## Recommendations

### Immediate Actions (next 30 days)
- [ ] **[Action 1]:** [Description — e.g., "Increase auto-scaling max replicas from 6 to 12"]. Owner: [@name]. Est. cost impact: $[X]/month.
- [ ] **[Action 2]:** [Description]. Owner: [@name]. Est. cost impact: $[X]/month.

### Medium-term Actions (30–90 days)
- [ ] **[Action 3]:** [Description — e.g., "Vertical scale DB primary from m5.xlarge to m5.2xlarge ahead of Q4 peak"]. Owner: [@name]. Est. cost: $[X]/month additional.
- [ ] **[Action 4]:** [Description]. Owner: [@name]. Est. cost: $[X]/month.

### Long-term Actions (90+ days)
- [ ] **[Action 5]:** [Description — e.g., "Re-architect job processing layer to use managed queue service to remove single-host bottleneck"]. Owner: [@name]. Design doc: [Link].
- [ ] **[Action 6]:** [Description]. Owner: [@name].

---

## Review Schedule

| Review type | Frequency | Owner | Trigger |
|-------------|-----------|-------|---------|
| Metric review | Monthly | [Name] | Standing calendar event |
| Threshold alert review | As triggered | On-call engineer | Threshold alert fires |
| Full capacity plan update | Quarterly | [Name] | Quarterly planning cycle |
| Emergency review | As needed | Engineering lead | >20% unexpected growth or major incident |

Pros and cons

Benefits

  • Converts reactive capacity scrambles into proactive, planned infrastructure investments with appropriate lead time for procurement and implementation.
  • Aligns engineering and finance teams on infrastructure cost trajectories, eliminating budget surprises and enabling better financial planning.
  • Identifies architectural bottlenecks that auto-scaling cannot address — database vertical limits, network quotas, stateful component constraints — before they become production incidents.
  • Provides a data-driven basis for evaluating architectural investments: when a re-architecture proposal claims to improve scalability, the capacity plan provides the baseline against which to measure the improvement.

Pitfalls

  • Projections based on linear extrapolation of current trends miss non-linear growth events (viral moments, major product launches) that are often the scenarios where capacity matters most.
  • Plans that are written annually and never reviewed become dangerously stale as the business context and system architecture evolve.
  • Over-provisioning based on worst-case projections leads to significant wasted infrastructure spend — balance buffer headroom against cost.
  • Focusing exclusively on compute and ignoring database connection limits, managed service quotas, and network egress costs — which are often the first constraints hit in cloud architectures.

Writing guidance

Gather actual metrics before writing projections. The most common failure mode in capacity planning is writing projections without first establishing a reliable measurement baseline. Before projecting forward, pull 90 days of historical data for every resource in scope: CPU, memory, disk, network, database connections, queue depths. Understand seasonality — is traffic flat throughout the year or do you have a peak season that creates a 3–5x multiplier? Projections applied to bad baselines produce unreliable plans.

Model the binding constraint, not the average. Most systems have one resource that will saturate first; that is your critical path. For I/O-intensive services, it is often the database. For compute-intensive services, it may be CPU or GPU. For data-heavy services, it may be storage growth or egress costs. Identify the binding constraint by measuring which resource is closest to its saturation threshold relative to projected growth, and make that the focus of your recommendations. Detailed projections for non-binding resources add document weight without actionable value.

Make cost projections visible and explicit. Engineers and engineering managers often have limited visibility into the infrastructure cost implications of growth. A capacity plan that shows the current monthly infrastructure cost and projects it 12 months forward — with and without the recommended changes — gives stakeholders the information they need to make funding decisions. Include both the cost of action (the recommended changes) and the cost of inaction (the incidents and emergency remediation that will occur if constraints are hit unprepared).

Common mistakes

  • Ignoring database connection limits: In cloud deployments, the database connection pool limit is frequently the first constraint hit as the number of application pods scales out. This is often invisible until it produces cascading failures.
  • Planning only for average load: Services that survive average load but fail at peak are the ones that cause major incidents. Capacity plans must account for peak traffic, factoring in seasonality, known business events, and a reasonable spike buffer.
  • No action items with owners: A capacity plan that produces recommendations without named owners and deadlines is a research document, not an operational plan. Every recommendation must be actionable.
  • Treating the plan as a one-time exercise: Business conditions, system architecture, and growth trajectories change. A capacity plan not reviewed for a year after business direction shifts may be actively misleading.

Review checklist

  • Is the current usage metrics section based on actual measured data with a specified measurement period (not estimates or guesses)?
  • Are growth projections tied to business assumptions that are explicitly documented and sourced (product roadmap, finance model, historical growth rate)?
  • Is the binding constraint (the resource that will saturate first) identified and is the recommendation focused on addressing it?
  • Does each recommendation have a named owner, a deadline, and an estimated cost impact?
  • Is a quarterly review meeting scheduled and a named owner assigned to maintain this document?

Example usage

  • Pre-peak season planning: An e-commerce platform produces a capacity plan in September for the Q4 holiday season. The plan identifies that the database connection pool will be exhausted at 3x current traffic. The team increases the pool size, provisions read replicas, and conducts a load test in October — preventing a database connection exhaustion incident that affected the previous year's Black Friday.
  • Post-fundraise growth: After a Series B, a SaaS company hires 15 new sales reps targeting enterprise accounts and projects 4x ARR growth. The engineering team produces a capacity plan that identifies PostgreSQL as the binding constraint at 3x current load and recommends a migration to a horizontally scalable database — a 6-month project that is scoped and staffed proactively rather than discovered during a scaling crisis.
  • Annual cloud cost review: A FinOps-driven capacity planning cycle reveals that 40% of provisioned compute is idle outside business hours due to poor auto-scaling configuration. The capacity plan produces recommendations to right-size instances and tune auto-scaling parameters, reducing monthly infrastructure costs by $18,000 while maintaining the same peak performance headroom.
  • SLO Document — capacity plans ensure that the infrastructure can sustain the latency and availability targets defined in the SLO document.
  • Threat Model — capacity plans for services handling sensitive data should be coordinated with the threat model to ensure that scaling changes do not introduce new security boundaries.
  • Scalability — patterns for designing systems that scale efficiently, referenced when capacity plans reveal architectural scaling limits.

Further reading