Capacity Planning

Forecast infrastructure capacity needs to prevent outages from resource exhaustion and avoid waste from over-provisioning. Covers demand modeling, load testing for capacity, resource saturation signals, and building capacity planning into your engineering process.

Capacity Planning is the process of ensuring that systems have sufficient resources to meet current and projected demand without over-provisioning. It matters when deploying new services, scaling existing ones, or during unexpected traffic spikes.

Understanding Resource Constraints

Capacity planning focuses on identifying resource bottlenecks before they cause service degradation. The key resources are CPU, memory, disk I/O, network bandwidth, and database connections.

To check current resource usage on a Linux system:


top -p $(pgrep -f your-service-name)

# Check disk usage
df -h

# Monitor network interface
iftop -i eth0

The most common failure mode is assuming that resource consumption scales linearly. A service that uses 10% CPU at 100 requests/second might suddenly consume 40% at 200 requests/second due to increased garbage collection or lock contention.

Measuring and Collecting Metrics

Use standard monitoring tools to collect capacity data. For example, Prometheus can scrape metrics from applications:

# Example Prometheus configuration for service metrics
scrape_configs:
  - job_name: 'service-metrics'
    static_configs:
      - targets: ['localhost:8080']

The key metric types are:

When collecting data, pay attention to the sampling interval. Metrics sampled every 10 seconds may miss short-lived spikes that cause capacity issues.

Identifying Bottlenecks

Use profiling tools to find resource-intensive operations:

# Profile a Go application with pprof
go tool pprof http://localhost:6060/debug/pprof/profile

# Monitor system calls for a running process
strace -p $(pgrep your-process) -c

Database queries are frequent bottlenecks. Use EXPLAIN ANALYZE in PostgreSQL:

EXPLAIN ANALYZE SELECT * FROM table WHERE condition = 'value';

The most common mistake is focusing only on the application layer while ignoring infrastructure constraints. A web server might be underutilized while the underlying database is saturated.

Estimating Future Demand

Capacity planning requires projecting future load based on historical data and business trends. The simplest model uses linear extrapolation:

Future Load = Current Load + (Growth Rate × Time)

For example, if your service handles 1000 requests/second today and grows at 5% monthly, it will need about 1050 requests/second next month.

Use standard time-series forecasting methods. If your data shows weekly patterns, account for that in projections:

# Example script to calculate moving averages for load prediction
awk '{sum += $1; if (NR > 7) {print sum/7; sum -= $(NR-7)}}' load-data.txt

The most critical error in demand estimation is ignoring seasonality and event-driven traffic. A retail site may handle 1000 requests/second during normal hours but require 5000 during a flash sale.

Resource Allocation Strategies

Overcommitment vs. Buffer

Allocate resources with either:

For example, if you need 100GB of storage, you might provision 80GB with overcommit or 120GB with buffer.

The decision depends on your tolerance for resource contention. Overcommitting risks performance degradation during peak usage, while buffering adds cost.

Horizontal vs. Vertical Scaling

Decide whether to scale by adding more instances (horizontal) or increasing instance size (vertical). For example:

# Scale a Kubernetes deployment
kubectl scale deployment my-app --replicas=5

Vertical scaling changes instance type:

# Change node type in cloud provider
aws ec2 modify-instance-attribute --instance-id i-1234567890abcdef0 --instance-type m5.large

Horizontal scaling is generally preferred for stateless services because it provides better fault tolerance and easier management.

Testing Capacity Limits

Use load testing to validate capacity assumptions:

# Example using wrk
wrk -t12 -c400 -d30s http://your-service.example.com/api/endpoint

The most important metric during load testing is response time percentiles. A service might appear fine under 1000 concurrent requests but fail at the 99th percentile.

Test with realistic data loads and request patterns. Simple GET requests don't represent real-world usage if your application makes complex database queries.

Handling Resource Exhaustion

When a system runs out of resources, it typically fails in predictable ways:

Monitor these failure modes using standard system tools:

# Check for memory issues
dmesg | grep -i "killed\|oom"

# Monitor disk space
watch df -h

Set up alerts for resource thresholds:

# Example Prometheus alert rule
- alert: HighMemoryUsage
  expr: container_memory_usage_bytes > 0.8 * container_memory_limit_bytes
  for: 5m
  labels:
    severity: warning

Capacity Planning Workflow

Step 1: Baseline Measurement

Establish current resource consumption:

# Collect baseline metrics over 24 hours
collectd -f /etc/collectd.conf

Record the number of active instances, their resource specifications, and observed load patterns.

Step 2: Demand Projection

Use historical data to project future needs. For example:

# Calculate average daily requests
grep "requests" log-file.txt | wc -l

Apply growth factors based on business forecasts.

Step 3: Resource Calculation

Determine required resources using:

Required Resources = Projected Load × Resource Per Request

Account for resource overhead from monitoring, logging, and other system components.

Step 4: Implementation

Deploy new capacity:

# Add capacity to a service
kubectl set resources deployment/my-app --requests=cpu=200m,memory=512Mi --limits=cpu=500m,memory=1Gi

Monitor the system after changes to ensure capacity meets requirements.

Common Mistakes and Failure Modes

Ignoring Resource Overhead

Applications consume more resources than their core logic requires. A service that needs 1GB of RAM might actually require 1.5GB when accounting for:

Misunderstanding Scaling Patterns

Some systems scale better horizontally than vertically. For example, a database with shared state might not benefit from adding more instances.

Underestimating Memory Leaks

Applications can gradually consume more memory over time. Use tools like Valgrind or heap profiling to detect leaks:

# Profile memory usage in Python
python -m memory_profiler your_script.py

Failing to Account for Contention

Multiple services on the same infrastructure compete for resources. A sudden increase in one service's CPU usage can starve others.

Capacity Planning Tools and Techniques

Use standard tools like:

These tools provide the raw data needed for capacity decisions without vendor-specific features.

Conclusion

Capacity planning is about making informed decisions based on measurable data rather than assumptions. It requires continuous monitoring, careful analysis of resource consumption patterns, and proactive adjustments to avoid performance degradation or service failures.

This page was rewritten on 16 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.