ArchitectMind
  1. Home
  2. Tutorials
  3. Book 9 · Cloud, Containers, DevOps & Production Architecture
  4. Volume VI
  5. Capacity
Book 9 · Volume VI — Production Architecture & Reliability Engineering · Topic 1.3

Capacity

Knowing your limits before users find them

11 min readStage 4 · Production & architecture10 interview questions
Chapter
Chapter 1 — Production Readiness
Prerequisites
Topic 1.1; Volume III scaling topics
You will be able to
Forecast demand, build capacity models from load tests, find breaking points, configure and pre-scale autoscaling, account for downstream limits and quotas, plan capacity for failures, add load shedding, and run capacity reviews
Covers
Capacity
On this page
  1. 1. Concept / Definition
  2. 2. Why It Exists
  3. 3. Core Concepts — Capacity
  4. 4. How It Works Internally — Building a Capacity Model
  5. 4A. Deep Dive — Downstream and Shared Limits
  6. 4B. Deep Dive — Autoscaling Behaviour
  7. 4C. Deep Dive — Capacity for Failure
  8. 4D. Deep Dive — ShopNow Diwali Capacity Plan
  9. 5. APIs / Features / Syntax
  10. 6. Practical Examples
  11. 7. Common Problems & Mistakes
  12. 8. Performance & Production Considerations
  13. 9. Architecture & Design Considerations
  14. 10. Interview Questions & Answers

1Concept / Definition

Capacity is the maximum load a system can handle while meeting its SLOs. Capacity planning forecasts demand, measures what each component can sustain, and ensures enough resources — plus headroom and failure tolerance — are available before peaks arrive, with graceful behaviour if forecasts are exceeded.

Checkout load test results
Figure 1 — Checkout load test results
Capacity model (checkout)
Figure 2 — Capacity model (checkout)
VocabularyMeaning
HeadroomSpare capacity above expected peak
SaturationHow full a resource is
KneeLoad point where latency degrades rapidly
Load sheddingDeliberately rejecting some work to protect the rest
Table 1 — Terms

2Why It Exists

Capacity failureConsequence
Traffic exceeds DB connectionsCheckout errors
Autoscaling too slow for spikeMinutes of degradation
Partner rate limit hitPayment failures
AWS quota reachedCannot scale
Table 2 — Why

3Core Concepts — Capacity

Load test typeQuestion answered
LoadDoes it meet SLOs at expected peak?
Stress / breakpointWhere does it break and how?
SpikeHow does it cope with sudden 5× jumps?
Soak (8–24 h)Leaks, slow degradation?
Failover under loadCapacity after losing an AZ?
Table 3 — Test types
Little's lawApplication
Concurrency = throughput × latency2,100 rps × 0.15 s = 315 concurrent requests
Thread/connection sizingPools sized from concurrency, not guesses
Table 4 — Queueing basics

4How It Works Internally — Building a Capacity Model

StepDetail
ForecastBusiness events, growth trends, marketing plans
Workload modelEndpoint mix, payload sizes, cache hit ratios from production
Per-unit capacityMax rps per pod at SLO (single-pod test)
Scale testLinear? Find shared bottlenecks (DB, locks, cache)
BreakpointIncrease until SLO breach; note failure mode
PlanPods, nodes, DB, downstream agreements, headroom
Table 5 — Method

4ADeep Dive — Downstream and Shared Limits

LimitCheckout valueMitigation
Aurora max connections5,000RDS Proxy; pool 20/pod
Payments partner rate limit7,000 rpsAgreed uplift for sale week
Redis ops/sec~1M per shardShards, client-side caching
Kafka partitions48Consumer parallelism ceiling
AWS quotas (EC2 vCPU, ENIs, NAT)Account limitsRaised 4 weeks before
Table 6 — The weakest link sets capacity

4BDeep Dive — Autoscaling Behaviour

MechanismReaction timeTuning
HPA (CPU/custom metrics)30–90 sStabilisation windows, target 60%
Karpenter nodes60–120 sSpare capacity via low-priority placeholder pods
KEDA (queue lag)30 sLag thresholds
Pre-scaling (scheduled)Before eventminReplicas raised 1 h before sale
Table 7 — Autoscaling has lag — plan for it
Headroom layers
Figure 3 — Headroom layers

4CDeep Dive — Capacity for Failure

ScenarioRequirement
Lose 1 of 3 AZsRemaining 2 AZs handle 100% peak → provision 150% of peak across 3
Lose a node groupKarpenter replaces; PDBs protect
Lose RedisDB can absorb fallback load at reduced rate (shedding)
Region failover (tier-0)DR region scales to peak within RTO
Table 8 — N+1 thinking

4DDeep Dive — ShopNow Diwali Capacity Plan

ItemPlan
Forecast peak6,300 checkout rps (3× normal peak)
Load test3.5× normal peak in staging-perf; breakpoint 4×
Pre-scaleCheckout min 69 pods from 17:00; nodes warmed via placeholders
DownstreamPayments uplift 9,000 rps; RDS Proxy; Redis +2 shards
QuotasvCPU +40%; NAT gateway per AZ
SheddingRecommendations disabled above 85% CPU; queue non-critical emails
ResultPeak 5,900 rps; p99 260 ms; 0 capacity incidents
Table 9 — Planned, tested, delivered

5APIs / Features / Syntax

JAVASCRIPT
// k6: realistic mix, ramp to 3.5× peak, thresholds tied to SLOs
import http from 'k6/http';
export const options = {
  scenarios: {
    ramp: { executor: 'ramping-arrival-rate', startRate: 500, timeUnit: '1s',
            preAllocatedVUs: 2000, stages: [
              { target: 2100, duration: '10m' }, { target: 7350, duration: '20m' },
              { target: 7350, duration: '30m' } ] },
  },
  thresholds: { http_req_failed: ['rate<0.005'], http_req_duration: ['p(99)<400'] },
};
export default function () {
  const r = Math.random();
  if (r < 0.6) http.get(`${__ENV.BASE}/cart`);
  else if (r < 0.9) http.post(`${__ENV.BASE}/checkout/price`, JSON.stringify(cart()));
  else http.post(`${__ENV.BASE}/checkout/pay`, JSON.stringify(payment()));
}
YAML
# Pre-scaling for a sale via a scheduled KEDA cron trigger alongside CPU
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata: { name: checkout, namespace: checkout }
spec:
  scaleTargetRef: { apiVersion: argoproj.io/v1alpha1, kind: Rollout, name: checkout }
  minReplicaCount: 17
  maxReplicaCount: 90
  triggers:
    - type: cron
      metadata: { timezone: Asia/Kolkata, start: "0 17 6 11 *",
                  end: "0 2 9 11 *", desiredReplicas: "69" }
    - type: cpu
      metricType: Utilization
      metadata: { value: "60" }
JAVA
// Load shedding: reject low-priority work when the service is saturated
@Component
class PriorityShedder implements HandlerInterceptor {
    private final Semaphore permits = new Semaphore(400);   // from Little's law sizing
    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object h) {
        boolean lowPriority = "recommendations".equals(req.getHeader("x-priority-class"));
        if (lowPriority && permits.availablePermits() < 40) {
            res.setStatus(503); res.setHeader("Retry-After", "5"); return false;
        }
        return true;
    }
}

6Practical Examples

6.1 Connection storm found in load test

At 2.5× peak, checkout pods scaled to 80 and opened 1,600 DB connections, exhausting Aurora. RDS Proxy and smaller pools were added before the sale.

6.2 Autoscaling lag during flash sale

A 10× spike in 30 seconds outpaced HPA and Karpenter; p99 hit 2 s for 3 minutes. Now flash sales trigger pre-scaling and placeholder pods keep warm node capacity.

6.3 Soak test found a leak

A 12-hour soak revealed heap growth from an unbounded cache; a size limit fixed it before it caused weekly restarts.

6.4 Worked example — per-pod capacity

MeasureValue
Max rps at p99 < 300 ms120
CPU at that load1.6 cores
Table 10 — Unit of capacity

6.5 Worked example — forecast inputs

InputSource
Last year's peak × growthAnalytics
Marketing push notifications scheduleMarketing
Table 11 — Business drives capacity

6.6 Worked example — capacity review agenda

TopicOwner
Forecasts, test results, limits, quotas, costsTeams + SRE + finance
Table 12 — Quarterly and before events

6.7 Worked example — interview whiteboard

PromptAnswer outline
"How do you ensure capacity for a 3× sales peak?""Forecast with business; model workload from production mix; single-pod tests for unit capacity; scale tests to find shared bottlenecks and the knee; plan pods/nodes/DB with 30% headroom and AZ-loss tolerance; check downstream limits (DB connections via proxy, partner rate limits, cache, partitions) and AWS quotas; pre-scale before the event, placeholder pods for fast node capacity; load shedding and degradation beyond plan; soak and spike tests; review results and cost."
Table 13 — Structured answer

6.8 Worked example — PayGrid capacity per cell

Cell capacityValue
Authorisations per cell2,500 tps at p99 < 150 ms
Add cells when > 60% utilisedScale by cells
Table 14 — Cell-based capacity

6.9 Worked example — anti-patterns

Anti-patternEffect
Testing with uniform synthetic requestsUnrealistic results
Ignoring downstream limitsSurprise failures
Relying only on autoscalingSpike lag
No breakpoint knowledgeUnknown margin
Table 15 — Common mistakes

6.10 Worked example — spike test

ProfileResult
0 → 5× in 30 sShedding kept checkout p99 < 800 ms
Table 16 — Behaviour under surprise

6.11 Worked example — cost trade-off

OptionMonthly cost
Always provisioned for peak₹48 L
Autoscale + pre-scale for events₹21 L
Table 17 — Elasticity saves money

6.12 Worked example — quota management

QuotaProcess
Service Quotas monitoring + alarms at 80%Request increases early
Table 18 — Quotas are capacity

6.13 Worked example — cache warm-up

EventAction
Pre-saleWarm product and price caches
Table 19 — Cold caches reduce capacity

6.14 Worked example — capacity dashboards

PanelMetric
Utilisation vs capacity per servicerps / max rps
Table 20 — Visible margin

6.15 Worked example — Little's law sizing

InputResult
300 rps/pod target × 0.2 s60 concurrent → Tomcat/virtual threads fine; DB pool 20 with queueing
Table 21 — Size pools deliberately

6.16 Worked example — interview follow-ups

Follow-upAnswer
"Why not just autoscale?"Lag, downstream limits and quotas
"How much headroom?"30%+ above forecast plus AZ-loss tolerance
Table 22 — Common probes

6.17 Worked example — checklist

Item✔
Forecast✔
Realistic load tests incl. breakpoint✔
Downstream limits and quotas✔
Autoscaling + pre-scaling✔
Failure capacity✔
Load shedding✔
Table 23 — Capacity baseline

6.18 Worked example — virtual threads and capacity

EffectWatch-out
More concurrent requests per podDownstream pools become bottleneck
Table 24 — Move the bottleneck consciously

6.19 Worked example — batch capacity

JobPlan
EOD reportsRun outside peak; throttle DB reads
Table 25 — Background work competes for capacity

6.20 Worked example — capacity alerts

AlertThreshold
Forecast breach (traffic > 80% of plan)Notify SRE
Table 26 — Early warning

6.21 Worked example — interview scenario

QuestionAnswer
"Load test passed but prod fell over"Check workload realism, data volumes, caches, downstream limits, test environment parity
Table 27 — Test fidelity

6.22 Worked example — test environment

EnvDetail
staging-perf (ephemeral, prod-sized for 1 day)Realistic without permanent cost
Table 28 — Cost-aware fidelity

6.23 Worked example — breakpoint failure modes

LoadSymptomComponent
3× peakp99 410 msCPU saturation (scales)
4× peakp99 1.9 s, errors 2%Inventory DB lock contention
Table 29 — Knowing *how* it breaks guides fixes

6.24 Worked example — capacity agreement with dependencies

ConsumerProviderAgreed peak
checkoutinventory8,000 rps
checkoutpayments9,000 rps (sale week)
Table 30 — Capacity contracts between teams

6.25 Worked example — post-event review

MetricPlanActual
Peak rps6,3005,900
Max pods69–9074
Cost₹3.1 L extra₹2.7 L
Table 31 — Improve next forecast

6.26 Worked example — data growth capacity

StoreGrowthPlan
orders table40 GB/monthPartitioning by month, archive after 2 years
Table 32 — Capacity includes storage

7Common Problems & Mistakes

MistakeFix
Unrealistic testsProduction mix
Hidden bottlenecksScale tests
Scaling lagPre-scaling
No overload planShedding
Table 33 — Mistakes and fixes

Load tests mislead in quieter ways too. A staging database with a tenth of production's data keeps indexes in memory and hides slow queries. Generators that repeat the same few product IDs make caches look far more effective than they are. Closed-model tools, where each virtual user waits for a response before sending the next request, slow down as the system slows and hide the queueing that real users create; this coordinated omission is why ShopNow uses k6's arrival-rate executors. The generator itself can saturate, so watch its CPU and network. Teams also report averages instead of p99, size headroom from hourly averages rather than the peak minute, and forget that client retries multiply load exactly when the system is struggling, so an overload test must include realistic retry behaviour.

8Performance & Production Considerations

ConsiderationPractice
Monitor utilisation vs capacityDashboards
Regular testsBefore events, quarterly
CostElastic capacity
Table 34 — Operating capacity

Day to day, capacity is a set of signals, not a yearly spreadsheet. Each service dashboard shows current rps against measured maximum rps per pod and in total, plus saturation signals that move before latency does: CPU, connection pool wait time, thread or virtual-thread backlog, queue depth and consumer lag. Alert when traffic passes 80% of planned capacity and when Service Quotas pass 80%. Per-pod capacity changes with every release, JDK upgrade or framework upgrade, so a short performance test in the pipeline re-baselines it and catches regressions early. Buy capacity in layers: Savings Plans for the steady baseline, Spot for elastic stateless work, and On-Demand Capacity Reservations for critical event days. Client retry budgets and circuit breakers keep a slow dependency from turning into a capacity incident.

9Architecture & Design Considerations

GuidelineDetail
Design for horizontal scaleStateless services
Protect shared resourcesProxies, pools
Graceful overloadPriority shedding
Table 35 — Design guidance

10Interview Questions & Answers

Q1BasicConcept

What is capacity planning?

Capacity planning is the practice of ensuring a system can handle expected demand while still meeting its SLOs, before that demand arrives. It has four parts. Forecast demand with the business, including growth, campaigns and events such as Diwali. Measure capacity, per pod and at scale, through realistic load tests up to the breaking point. Plan resources with headroom and failure tolerance, including downstream limits such as database connections, partner rate limits and AWS quotas. Then define what happens beyond the plan, through autoscaling, pre-scaling and load shedding. It is a continuous cycle, revisited quarterly and before every major event, not a one-off sizing exercise.

Q2BasicConcept

What is headroom?

Headroom is spare capacity deliberately kept above the expected peak, so that forecast errors, sudden spikes, autoscaling lag and partial failures do not push the system past its knee, where latency climbs sharply. It is expressed as a margin over forecast, ShopNow uses at least 30%, plus a separate allowance for losing an availability zone. Headroom exists in layers: running pods, warm spare node capacity from placeholder pods, and reserved limits in databases and downstream services. Too little and the first surprise becomes an incident; too much and you pay for idle resources. Tier-0 paths such as checkout justify more headroom than internal reporting.

Q3IntermediateConcept

What load test types exist?

Each test type answers a different question. A load test checks whether the system meets its SLOs at the expected peak with a realistic request mix. A stress or breakpoint test keeps increasing load until SLOs break, revealing where the knee is and how the system fails. A spike test applies sudden jumps, such as five times normal in 30 seconds, to see how autoscaling and shedding cope. A soak test runs normal load for 8 to 24 hours to expose leaks, connection exhaustion and slow degradation. A failover test removes an AZ, node group or cache under load to check that the remaining capacity holds.

Q4IntermediateEstimation

What is Little's law used for?

Little's law says that the average number of requests in a system equals throughput multiplied by the average time each request spends there. It lets you size thread pools, connection pools and semaphores from measured numbers rather than guesses. For example, ShopNow checkout at 2,100 requests per second with 0.15 second latency has about 315 requests in flight across the fleet. Per pod, a target of 300 requests per second at 0.2 seconds means about 60 concurrent requests, which is fine for Tomcat or virtual threads. The same maths shows the risk: if latency doubles during an incident, concurrency doubles too and pools exhaust.

Q5Senior EngineerTricky

Why isn't autoscaling enough?

Autoscaling reacts to load after it arrives, and it has limits it cannot see. HPA takes 30 to 90 seconds to act and new nodes another one to two minutes, so a tenfold flash-sale spike in 30 seconds overwhelms the fleet before help arrives; ShopNow saw a p99 of 2 seconds for three minutes. Scaling pods does not scale shared dependencies: more pods can exhaust Aurora connections or a partner rate limit faster. Account quotas for vCPU, ENIs or IP addresses can stop scaling entirely. So combine autoscaling with pre-scaling for known events, warm placeholder capacity, downstream agreements, raised quotas and load shedding.

Q6Senior EngineerScenario

How do you find shared bottlenecks?

Run scale tests beyond single-pod capacity and look for where throughput stops growing linearly. First measure one pod's maximum rps at the SLO, for example 120. Then test at increasing pod counts: if 10 pods give 1,200 rps but 40 give only 3,000, something shared is saturating. Instrument the shared components during the test: database connections, CPU and lock waits, cache operations per shard, Kafka partitions and consumer lag, NAT gateway throughput and partner response times. At ShopNow, a test at 2.5 times peak showed 80 pods opening 1,600 connections and exhausting Aurora, which led to RDS Proxy and smaller pools before the sale.

Q7Technical ArchitectEstimation

How do you plan for AZ loss?

Provision so that the remaining zones can carry full peak load without help from autoscaling. With three AZs, losing one leaves two thirds of capacity, so each AZ must handle half of peak, which means provisioning about 150% of peak across all three. With autoscaling you can provision less and rely on scale-out, but only if AZ failure does not also block scaling through capacity shortages or quotas, so tier-0 services normally keep static stability. Spread pods with topology spread constraints, keep databases Multi-AZ with replicas able to take writes, and test the assumption by removing an AZ during a load test rather than trusting the arithmetic.

Q8Technical ArchitectDesign

What is load shedding?

Load shedding is deliberately rejecting some work when a service is near saturation so that the most important work keeps meeting its SLOs, instead of everything slowing down together. You classify requests by priority, for example checkout payment over recommendations, and when a saturation signal crosses a threshold, such as available permits, CPU or queue depth, low-priority requests get a fast 503 with Retry-After. Degradation goes with it: disable non-essential features and queue non-critical work such as emails. ShopNow disables recommendations above 85% CPU. Shedding must be fast and cheap, happen early in the request, and be paired with client retry budgets so rejected work does not return as a retry storm.

Q9Solution ArchitectTrade-off

How do you balance cost and capacity?

Pay for guaranteed capacity only where it is needed, and make the rest elastic. Provisioning permanently for peak would cost ShopNow about ₹48 lakh a month, against ₹21 lakh with autoscaling plus pre-scaling for known events. Headroom is set by tier: checkout and payments get generous headroom and AZ-loss tolerance, while reporting runs with little and is throttled or shed first. Buy the steady baseline with Savings Plans, run elastic stateless work on Spot, and reserve capacity for critical event days. Use ephemeral, production-sized test environments instead of permanent ones. Compare plan versus actual after each event, since Diwali's extra cost came in at ₹2.7 lakh against ₹3.1 lakh planned.

Q10Solution ArchitectBehavioural

What should a capacity review include?

A capacity review brings product, marketing, engineering, SRE and finance together, quarterly and before every major event, because no single team holds all the inputs. Cover the demand forecast and the business events behind it, load-test results including per-pod capacity, breakpoints and failure modes, and current utilisation against capacity per service. Review shared limits: database connections, cache shards, partitions, partner agreements and AWS quotas. List risks and mitigations such as pre-scaling, shedding and degradation, and cost against budget. Finish with owners and dates for every action, then review the last event's plan against actuals so the next forecast improves. Clear owners matter more than slides.

Newsletter

Get new tutorials every week

New ArchitectMind tutorials and interview questions, once a week. No spam, unsubscribe anytime.

Almost done! Check your inbox and click the confirmation link to complete your subscription.
Keep going in Book 9

Cloud, Containers, DevOps & Production Architecture

Volume I · Topic 1.1

What Is Cloud Computing?

Cloud Computing & Cloud Architecture Fundamentals

Volume I · Topic 1.2

Cloud Service Models

Cloud Computing & Cloud Architecture Fundamentals

Volume I · Topic 1.3

Cloud Deployment Models

Cloud Computing & Cloud Architecture Fundamentals

Volume II · Topic 1.1

Regions

AWS & Cloud Services

Volume II · Topic 1.2

Availability Zones

AWS & Cloud Services

Volume II · Topic 1.3

Edge Locations

AWS & Cloud Services

Volume III · Topic 1.1

Containers

Containers & Kubernetes

Volume III · Topic 1.2

Containers vs Virtual Machines

Containers & Kubernetes

Volume III · Topic 1.3

Container Lifecycle

Containers & Kubernetes

Volume IV · Topic 1.1

IaC Fundamentals

Infrastructure as Code & Platform Engineering

Volume IV · Topic 1.2

Declarative vs Imperative

Infrastructure as Code & Platform Engineering

Volume IV · Topic 1.3

Immutable Infrastructure

Infrastructure as Code & Platform Engineering

Volume V · Topic 1.1

DevOps

CI/CD & DevOps Architecture

Volume V · Topic 1.2

Development + Operations

CI/CD & DevOps Architecture

Volume V · Topic 1.3

Continuous Integration

CI/CD & DevOps Architecture

Volume VI · Topic 1.1

Production Readiness Review

Production Architecture & Reliability Engineering

Volume VI · Topic 1.2

Operational Requirements

Production Architecture & Reliability Engineering

Volume VII · Topic 1.1

Cloud-Native Principles

Cloud-Native Architecture & Multi-Region Systems

Volume VII · Topic 1.2

Twelve-Factor Applications

Cloud-Native Architecture & Multi-Region Systems

Volume VII · Topic 1.3

Immutable Infrastructure

Cloud-Native Architecture & Multi-Region Systems

Volume VIII · Topic 1.1

Architecture Drivers

Cloud Architecture Design, Cost & Migration

Volume VIII · Topic 1.2

Cloud Service Selection

Cloud Architecture Design, Cost & Migration

Volume VIII · Topic 1.3

Managed vs Self-Managed

Cloud Architecture Design, Cost & Migration