System Design Fundamentals and Capacity Estimation - Complete Notes

A language-neutral method for turning an unclear product idea into measurable requirements, capacity estimates, architecture decisions, failure plans, and a design that can be explained, tested, operated, and improved.

00. The system-design mental model

System design is the disciplined process of choosing boundaries, data flows, state, and failure behavior that satisfy a specific workload under explicit constraints.

A design is not a collection of fashionable components. It is an argument. Requirements describe the result users and the business need. Estimates describe the expected pressure. The architecture describes how work and state move through the system. Trade-offs explain why this shape is more suitable than credible alternatives. Measurements and tests show whether the argument remains true in production.

Think of designing a bridge. The answer is not "use steel." The engineer first asks what must cross the bridge, how often, in what weather, how much failure is tolerable, how repairs will happen, and what budget exists. Software design follows the same pattern. A database, queue, cache, or framework is a material selected after the load and constraints are understood.

Question Design output Failure when skipped
What must the system do? Functional requirements and critical user flows Solving the wrong problem well
How well must it do it? Latency, availability, durability, security, and cost targets No objective way to judge the design
How much work and data exist? Traffic, concurrency, bandwidth, storage, and growth estimates Overbuilding, underbuilding, or missing a bottleneck
Where does state live and move? APIs, events, data models, ownership, and consistency boundaries Hidden coupling and unreliable dual writes
What fails? Failure modes, fault domains, degraded modes, and recovery plans A happy-path diagram mistaken for a production design
How will we know? SLIs, SLOs, tests, dashboards, alerts, and review triggers Opinions replace evidence
The core loop

Clarify, quantify, design, challenge, measure, and revise. Every later topic in distributed systems adds tools to this loop, but never replaces it.

01. Start with requirements, not components

Requirements define the decision space. Components are possible answers inside that space.

Functional requirements

Functional requirements describe observable capabilities. They should be written as user or system flows with clear inputs, outputs, and important state changes. "Build a URL shortener" is not precise enough. A useful first scope might say:

  • Create a short URL for a valid destination URL.
  • Redirect a short code to its active destination.
  • Allow an owner to disable or expire a link.
  • Record aggregate click counts without slowing the redirect path.
  • Prevent a disabled, malicious, or expired link from redirecting.

Separate must-have behavior from optional behavior. Custom aliases, detailed analytics, link previews, geographic routing, QR codes, and campaign management can radically change the design. Do not silently include them. State what is excluded and when the decision should be revisited.

Critical flows and correctness

Not every flow has the same importance. Identify the business-critical and safety-critical paths. A payment authorization may require stronger consistency and auditability than an analytics counter. A redirect may prioritize latency and availability, while link creation can accept a slightly slower response.

Flow Correctness rule Likely priority
Create link One allocated code identifies exactly one destination Correctness, durability, then latency
Redirect Return the current allowed destination or a clear failure Availability and tail latency
Disable link Disabled links stop redirecting within the stated propagation bound Security and bounded staleness
Count click Approximate analytics may lag but must not block redirects Throughput and cost

High-value clarification questions

  • Who are the users, tenants, administrators, and dependent systems?
  • Which operations are reads, writes, streams, jobs, or scheduled work?
  • Which result must be immediately consistent, and which may be stale?
  • What data loss, duplication, or reordering is acceptable?
  • What happens when a dependency is slow, unavailable, or returns an uncertain result?
  • Which regions, devices, protocols, accessibility needs, and regulations apply?
  • What is the expected launch load, peak load, growth rate, and retention period?
  • Which requirement is expensive enough that changing it would simplify the design?
Do not invent precision

If the stakeholder does not know a number, choose a documented assumption and continue. A visible assumption can be corrected. A hidden assumption silently corrupts every downstream decision.

02. Non-functional requirements and quality attributes

Non-functional requirements describe how the system must behave while delivering its functions.

Attribute Useful question Example target
Latency How quickly must a user-visible operation finish? 99% of redirects complete within 150 ms
Throughput How much useful work must finish per unit of time? Sustain 20,000 redirects per second at peak
Availability What fraction of valid requests must succeed? 99.95% successful redirects per calendar month
Durability What acknowledged state may be lost? No acknowledged link creations lost after a single-zone failure
Consistency How current and coordinated must observations be? A disabled link stops resolving globally within 60 seconds
Scalability How efficiently does capacity grow with resources? Double redirect capacity with at most 2.2 times the serving cost
Security What must be protected from whom? Only an owner or administrator can mutate a link
Privacy Which personal data is collected, retained, or shared? Do not store raw client IP addresses in long-term analytics
Operability Can people detect, diagnose, mitigate, and recover? On-call can disable link creation independently of redirects
Cost What budget and cost-per-unit are acceptable? Keep redirect infrastructure below a stated cost per million requests

Quality attributes conflict. Stronger durability may add synchronous replicas and latency. Lower tail latency may require more idle capacity. More detailed analytics can increase storage cost and privacy risk. A design review should expose these tensions and state which attribute wins for each critical flow.

03. SLIs, SLOs, SLAs, and error budgets

A reliability statement is useful only when its event, threshold, population, and measurement window are explicit.

Service level indicator, or SLI
A quantitative measure of service behavior, such as the proportion of valid redirect requests that succeed or the distribution of end-to-end latency.
Service level objective, or SLO
A target for an SLI over a defined window, such as 99.95% successful redirects over a calendar month.
Service level agreement, or SLA
A business or contractual commitment that normally includes consequences when the commitment is not met. An internal SLO is commonly stricter than the public SLA.
Error budget
The allowed amount of unsuccessful service implied by an SLO. For a success-rate SLO, the budget is usually 1 - SLO over the measurement window.
A precise request-based SLO
SLI =
  valid redirect requests returning the correct redirect or approved not-found response
  -------------------------------------------------------------------------------
  all valid redirect requests received at the public edge

SLO =
  SLI >= 99.95% over each calendar month

Latency objective =
  99% of successful redirects complete within 150 ms at the public edge

Define which requests count. Exclude synthetic load only if it is separately controlled. Decide whether client cancellations, invalid input, rate-limited abuse, and dependency-caused failures count. Measure as close to the user as practical. A server may report success after the client has already timed out.

Availability and budget math

Time-based availability is intuitive but request-based availability often matches user experience better. A ten-minute outage at peak traffic affects more requests than a ten-minute outage during an idle period.

Monthly availability target Approximate unavailable time in a 30-day month Error budget per 1,000,000 requests
99% 7 hours 12 minutes 10,000 failed requests
99.9% 43 minutes 12 seconds 1,000 failed requests
99.95% 21 minutes 36 seconds 500 failed requests
99.99% 4 minutes 19 seconds 100 failed requests

More nines are not free. They demand smaller failure domains, more automation, safer changes, faster detection, tested recovery, dependency alignment, and spare capacity. Choose a target from user and business needs, not prestige.

04. Build a workload model

Capacity estimates start with counts and distributions, not machine types.

Record at least these workload dimensions:

  • Daily and monthly active users, tenants, devices, or producers.
  • Operations per active user and the read-to-write ratio.
  • Average, peak, and exceptional traffic rather than one average value.
  • Request and response sizes, object sizes, and batch sizes.
  • Data retention, update frequency, deletion policy, and annual growth.
  • Geographic distribution and time-zone-driven peaks.
  • Interactive, background, scheduled, and replay traffic.
  • Hot-key, celebrity, tenant-skew, and large-payload distributions.

Average is a baseline, not a capacity target

Average requests per second are useful for checking arithmetic. Production capacity must account for peaks, retries, maintenance, deployments, failures, uneven balancing, and future growth. Model at least:

  • Normal peak: a predictable busy interval the system must serve routinely.
  • Failure peak: the same demand after losing a zone, replica, or dependency path.
  • Exceptional event: a campaign, breaking-news event, customer import, or replay.
  • Recovery load: queued work, cache warming, replication catch-up, and retries.
Core workload formulas
average requests per second =
  requests per day / 86,400

peak requests per second =
  average requests per second * measured or assumed peak factor

concurrent in-flight requests =
  arrival rate per second * average time in system in seconds

annual objects =
  writes per second * 86,400 * 365

raw storage =
  object count * average stored bytes per object
Peak factors are workload-specific

A guessed five-times peak is not a law. Record it as an assumption, instrument real traffic, and replace it with observed percentiles. Some workloads are nearly flat. Others can jump by hundreds of times in seconds.

05. Back-of-the-envelope estimation

Estimation finds orders of magnitude, impossible assumptions, and likely bottlenecks before detailed implementation begins.

Traffic and concurrency

Separate operations because their costs differ. A cached lookup, database write, full-text search, image upload, and analytics aggregation cannot share one meaningful requests-per-second number. Estimate each critical flow.

Concurrency connects throughput and latency. Little's Law states that, for a stable system, average items in the system equal average arrival rate multiplied by average time in the system. At 20,000 requests per second and 0.1 seconds average completion time, approximately 2,000 requests are in flight. If latency rises to one second while arrivals stay constant, concurrency becomes 20,000. That can exhaust sockets, threads, memory, database connections, and queues.

Storage

Estimate more than payload bytes:

Storage budget
logical data
+ row or document metadata
+ primary and secondary indexes
+ write-ahead or replication logs
+ replicas
+ temporary compaction or migration space
+ backups and retained snapshots
+ safety headroom
= provisioned storage

Compression, deletion, index structure, update rate, and replication can move the result substantially. State a range and identify the inputs that need measurement.

Bandwidth

Estimate ingress and egress separately. Include protocol overhead, replication, backups, cache fills, internal fan-out, and cross-region traffic. A 500-byte response at 20,000 responses per second is 10 MB/s of application payload, or about 80 Mb/s before overhead. If one external request causes five internal requests, internal network traffic can dominate.

Compute and instance count

Convert load into instances only after benchmarking representative work. Use a safe operating capacity below the observed breaking point. If one instance can sustain 5,000 requests per second in a realistic test but latency begins to rise sharply above 60% CPU, design around the tested safe capacity, not the final successful request.

Instance estimate with failure capacity
safe capacity per instance = 3,000 requests/second
normal peak               = 20,000 requests/second
instances for traffic     = ceil(20,000 / 3,000) = 7

Three-zone layout:
  4 instances per zone = 12 total
  lose one zone        = 8 remaining
  remaining capacity   = 8 * 3,000 = 24,000 requests/second

This simple model has deliberate spare capacity and survives a zone loss at normal peak. It still requires tests for balancing efficiency, dependency capacity, deployment overlap, and exceptional traffic.

Small TypeScript estimation helper

A script can make assumptions repeatable, but the model matters more than the language. Keep the variables readable and store the assumptions beside the result.

TypeScript: transparent capacity arithmetic
type EstimateInput = {
  monthlyWrites: number;
  readsPerWrite: number;
  peakFactor: number;
  averageLatencyMs: number;
  bytesPerRecord: number;
  retentionYears: number;
};

function estimate(input: EstimateInput) {
  const secondsPerMonth = 30 * 24 * 60 * 60;
  const averageWriteRps = input.monthlyWrites / secondsPerMonth;
  const averageReadRps = averageWriteRps * input.readsPerWrite;
  const peakReadRps = averageReadRps * input.peakFactor;
  const concurrentReads = peakReadRps * (input.averageLatencyMs / 1000);
  const retainedRecords = input.monthlyWrites * 12 * input.retentionYears;
  const rawStorageBytes = retainedRecords * input.bytesPerRecord;

  return {
    averageWriteRps,
    averageReadRps,
    peakReadRps,
    concurrentReads,
    retainedRecords,
    rawStorageBytes,
  };
}

Production models should include ranges and sensitivity analysis. If doubling one assumption changes the architecture, that assumption deserves measurement and an explicit review trigger.

06. Latency, throughput, and percentiles

Throughput says how much work completes. Latency says how long individual work takes. Both change under load.

Averages hide users in the slow tail. Report a distribution using percentiles such as p50, p95, p99, and p99.9. If p99 is 400 ms, approximately one request in one hundred is slower than 400 ms during the measurement window. Percentiles must identify the population, location, and window.

Measure What it reveals Common mistake
p50 Typical request experience Treating it as proof that almost everyone is fast
p95 Broad tail behavior Ignoring the remaining 5% at high volume
p99 or p99.9 Rare but user-visible slow paths Using a sample too small to estimate it reliably
Throughput Completed useful work per interval Counting accepted or queued work as completed work
Saturation How close a constrained resource is to its useful limit Watching CPU while a connection pool or lock is exhausted

Latency normally rises nonlinearly near saturation because work waits in queues. A service can appear healthy at average load and cross a performance cliff during a modest spike. Load tests should find both the sustainable capacity and the failure behavior beyond it.

07. Availability, reliability, durability, and recoverability

These words describe different promises and should not be used interchangeably.

Availability
The system can provide the defined service when requested.
Reliability
The system continues to perform correctly over time under stated conditions.
Durability
Acknowledged data remains intact over the promised retention period.
Recoverability
The system can restore service and data within stated recovery targets.
Resilience
The system can absorb, adapt to, and recover from faults without unacceptable harm.

A service may be highly available but return stale or incorrect data. A storage system may keep data durably while its read API is unavailable. A replicated database may lose multiple copies through one bad deletion propagated everywhere. Backups improve recoverability only after restore tests demonstrate that they are complete and usable.

Dependency availability

A serial critical path cannot be more available than its required dependencies. If a request requires services A and B, each with 99.9% independent availability, the rough combined availability is 0.999 * 0.999 = 99.8001%. Real failures are often correlated, so simple multiplication can be optimistic.

Remove unnecessary hard dependencies from critical paths. Cache stable configuration, make optional analytics asynchronous, define degraded modes, and ensure the control plane is not required for every data-plane request.

08. Boundaries, state, and critical paths

A useful high-level design shows ownership and communication, not every class or cloud icon.

For each component, answer:

  • What responsibility and data does it own?
  • Which API, event, or protocol crosses its boundary?
  • Is the interaction synchronous or asynchronous?
  • What is the timeout, retry, and idempotency behavior?
  • What happens if it is slow, unavailable, duplicated, or partitioned?
  • How does it scale, deploy, observe, secure, and recover?
Minimal read path
Client
  |
  v
Public edge and rate limit
  |
  v
Stateless redirect service
  | cache hit
  +----------------------> Return redirect
  |
  | cache miss
  v
Durable link store ------> Fill cache ------> Return redirect
  |
  +---- asynchronous click event ----> Analytics pipeline

The critical redirect path excludes analytics. A slow analytics system should not make redirects fail. This is an architectural decision derived from flow priority, not a preference for queues.

Single points of failure and hidden shared fate

Multiple instances do not create redundancy when they share one database, one network path, one certificate, one deployment, one configuration service, or one operator mistake. Identify shared fate across compute, storage, network, identity, configuration, deployment, and people.

09. Failure domains, redundancy, and headroom

Redundancy is useful only when replicas do not fail together and the remaining capacity can carry the load.

Common failure domains include a process, host, rack, zone, region, network provider, identity provider, deployment wave, software version, account, and administrative control plane. Map each critical component to the failures it must survive.

Design question Evidence required
Can one zone fail? Remaining-zone capacity, data placement, routing, and a fault test
Can one deployment fail? Progressive rollout, compatibility, fast rollback, and separated waves
Can the control plane fail? Data plane continues with last known safe configuration
Can a credential be revoked? Rotation procedure that does not require simultaneous global change
Can backup recovery meet the promise? Timed restore tests and verified application-level integrity

Headroom is deliberate spare capacity for peaks, failures, deployments, and uncertainty. It is not waste when it protects an explicit reliability target. Measure headroom at every constrained dependency, not only at stateless application servers.

10. Diagrams and decision records

Different diagrams answer different questions. One overloaded diagram answers none of them well.

  • Context diagram: users, external systems, trust boundaries, and the system.
  • Container or component diagram: deployable units, data stores, and ownership.
  • Data-flow diagram: where sensitive or durable data enters, moves, and rests.
  • Sequence diagram: ordering, timeouts, retries, and failures in one flow.
  • Deployment diagram: zones, regions, networks, replicas, and fault domains.
  • State machine: valid states, transitions, retries, and terminal outcomes.

Label arrows with protocols and whether they are synchronous or asynchronous. Label stores with the data they own. Add trust and failure boundaries. A diagram that says only "service talks to database" hides the decisions that reviewers need.

Architecture decision records

An architecture decision record, or ADR, captures context, the chosen decision, alternatives, consequences, and review triggers. It prevents a current decision from becoming an unexplained permanent rule.

Small ADR template
Title:
Status:
Context and constraints:
Decision:
Alternatives considered:
Positive consequences:
Negative consequences and risks:
Measurements and safeguards:
Revisit when:

11. A repeatable design method

A consistent sequence keeps interviews and real design reviews focused on the highest-risk decisions.

  1. Clarify scope. Identify actors, must-have flows, exclusions, correctness rules, and business priorities.
  2. Define quality targets. State latency, availability, durability, consistency, security, privacy, retention, recovery, and cost requirements.
  3. Estimate load. Calculate average and peak traffic, concurrency, bandwidth, storage, growth, and failure capacity.
  4. Define contracts and data. Sketch APIs, events, idempotency, primary entities, ownership, indexes, and state transitions.
  5. Draw the high-level design. Show critical synchronous paths, asynchronous work, stores, caches, and external dependencies.
  6. Deep-dive the risks. Examine hot paths, contention, consistency, partitions, security boundaries, data loss, overload, and migrations.
  7. Challenge failures. Remove a process, zone, dependency, credential, network path, and operator assumption. Describe degraded behavior and recovery.
  8. Make it operable. Define SLIs, dashboards, alerts, runbooks, capacity signals, deployment safety, and restore tests.
  9. Summarize trade-offs. State what the design optimizes, what it sacrifices, and which changes would force a redesign.
Interview pacing

Clarify before drawing. Estimate before scaling. Present one simple correct design before evolving it. Spend depth on the largest risk instead of naming every technology you know.

12. Worked design: URL-shortening service

This first-pass design demonstrates the method. It is not the only correct design.

Requirements and assumptions

  • Create 100 million short links per month.
  • Serve 100 redirects for every link creation.
  • Retain links for five years unless an owner deletes or expires them.
  • Normal peak is five times average traffic.
  • Redirect SLO is 99.95% successful requests per month.
  • Redirect latency target is p99 below 150 ms at the public edge.
  • A disabled link must stop redirecting globally within 60 seconds.
  • Click analytics may be delayed and may use approximate aggregates.

Custom aliases, detailed visitor analytics, preview generation, and billing are outside the first version. The design leaves places to add them later.

Capacity calculation

Traffic
100,000,000 creates/month
/ 2,592,000 seconds/month
= about 38.6 average creates/second

100 redirects per create
= about 3,860 average redirects/second

5x normal peak
= about 200 creates/second
= about 20,000 redirects/second

At 100 ms average redirect time:
20,000 * 0.1 = about 2,000 concurrent redirects
Storage
100,000,000 links/month * 12 * 5 years
= 6,000,000,000 retained links

Assume 250 bytes logical storage/link:
6 billion * 250 bytes = about 1.5 TB raw

With 3 replicas:
about 4.5 TB before indexes, logs, backups, migration space, and headroom

Planning range:
about 7 to 10 TB provisioned for primary serving data and indexes,
with backups budgeted separately

The range matters more than false precision. Measure actual destination length, metadata, index size, compression, expiration, and backup policy before provisioning.

Short-code space

Eight base-62 characters provide 62^8, or roughly 218 trillion combinations. Six billion retained links occupy a small fraction of that space. Random generation still needs a uniqueness check and retry. An allocated numeric ID encoded as base 62 avoids random collisions but introduces an ID-allocation and predictability decision. The API must also prevent enumeration from exposing private metadata.

Minimal API contracts

Language-neutral HTTP surface
POST /links
Idempotency-Key: client-generated-key
{ "destination": "https://example.com/article", "expiresAt": null }

201 Created
{ "code": "aZ91kLm2", "shortUrl": "https://sho.rt/aZ91kLm2" }

GET /{code}
302 Found
Location: https://example.com/article

DELETE /links/{code}
204 No Content

Creation uses an idempotency key so a client timeout and retry do not create multiple links. Redirect returns not found or gone for missing, expired, disabled, or blocked codes according to a documented policy.

Data model

Field Purpose
code Unique primary lookup key
destination Validated destination URL
owner_id Authorization and tenant boundary
status Active, disabled, expired, or blocked
created_at, expires_at Lifecycle and retention
version Cache invalidation and concurrent update control

The primary access pattern is an exact lookup by code. The owner-management path needs a secondary access pattern by owner and creation time. Click analytics should not update the primary link row on every redirect because that creates contention on popular links.

High-level architecture

First production shape
                         +----------------------+
Client -> Edge -> Router | Redirect service     |
                         +----------+-----------+
                                    |
                              cache | lookup
                                    v
                         +----------------------+
                         | Distributed cache    |
                         +----------+-----------+
                                    | miss
                                    v
                         +----------------------+
                         | Durable link store   |
                         +----------------------+

Redirect service -> durable event buffer -> analytics consumers -> aggregate store

Authenticated client -> management service -> durable link store -> cache invalidation

Redirect instances are stateless and spread across failure domains. The cache serves hot codes and reduces database reads. Cache misses fall through to the durable store and fill the cache. The redirect response does not wait for analytics. Management writes commit to the durable store before invalidation is published.

Consistency and failure behavior

  • Cache unavailable: fall back to a protected database path with concurrency limits. Do not allow cache failure to overload the database.
  • Store unavailable: cached active links may continue during a carefully bounded degraded mode, but new links and cache misses fail clearly.
  • Invalidation delayed: cache entries use a TTL no greater than the promised disable propagation window, and urgent blocks may use an edge denylist.
  • Analytics unavailable: buffer events durably up to a capacity limit, sample or drop noncritical analytics according to policy, and keep redirects serving.
  • One zone unavailable: routing removes the zone and remaining zones have enough tested capacity for peak traffic.

Evolution triggers

Do not shard on day one only because the long-term count is large. Begin with a store that meets the current load and has a measured growth path. Revisit partitioning when storage size, write rate, index maintenance, replica lag, or operational windows approach tested limits. Revisit global placement when user latency or regional recovery targets require it.

13. Security, privacy, and abuse requirements

Security is a design input, not a final checklist added after components are chosen.

At minimum, identify:

  • Assets: credentials, destinations, ownership, click metadata, and administrative controls.
  • Actors: anonymous users, owners, administrators, services, attackers, and insiders.
  • Trust boundaries: public edge, internal services, data stores, operations, and third parties.
  • Abuse: phishing, malware redirects, enumeration, scraping, denial of service, and quota evasion.
  • Privacy: IP addresses, user agents, location, referrers, retention, deletion, and access logs.

Validate destination schemes and length, prevent unsafe internal destinations where server-side fetching exists, rate-limit creation and redirect abuse separately, authorize mutations by owner, audit administrative actions, encrypt traffic and durable data, rotate credentials, and define a fast block mechanism. Avoid collecting analytics fields that have no product purpose.

Security can change capacity

Authentication, encryption, malware scanning, audit logging, and rate-limit checks consume CPU, storage, and dependency capacity. Include them in the critical path and benchmark, not only in a policy document.

14. Production readiness and observability

A design is incomplete until operators can understand its health and safely change it.

Signals

  • Request rate, success rate, latency percentiles, and payload distributions by operation.
  • Queue depth, age of oldest work, consumption rate, retries, and dead-letter volume.
  • Cache hit ratio, miss latency, eviction rate, hot keys, errors, and memory pressure.
  • Database latency, throughput, connection use, lock waits, replication lag, and storage growth.
  • CPU, memory, garbage collection where applicable, sockets, threads, event-loop lag, and saturation.
  • Error-budget consumption and burn rate for each critical SLO.

Break down metrics only by bounded-cardinality dimensions. A short code, URL, user ID, or request ID must not become a metric label. Use logs or traces for high-cardinality investigation, with redaction and access controls.

Safe change

  • Backward-compatible API, event, and schema changes.
  • Progressive rollout with automated health comparison and rollback.
  • Capacity for old and new versions during deployment.
  • Feature flags with owners, expiry, safe defaults, and failure behavior.
  • Runbooks for dependency failure, overload, data corruption, credential loss, and rollback.
  • Regular restore, failover, and degraded-mode tests.

15. Testing the design assumptions

Tests should target the claims that justify the architecture.

Test Question answered
Unit and property tests Are estimators, ID rules, state transitions, and validators correct?
Integration tests Do contracts, persistence, timeouts, and error mappings work with real dependencies?
Contract tests Can clients and services evolve independently without accidental breakage?
Load test Does the system meet SLOs at normal peak and expected data size?
Stress test Where is the performance cliff and how does overload fail?
Soak test Do leaks, compaction, cache churn, or background work appear over time?
Fault test Does losing a process, zone, network path, cache, or store match the failure plan?
Recovery test Can operators restore service and data within the promised time?

Use production-shaped data and traffic. A database with ten rows does not exercise index depth, cache behavior, compaction, query planning, or storage limits. A load test with no failures does not validate failure capacity.

16. Trade-offs and review triggers

A good design makes reversible decisions cheaply and records when expensive decisions must be revisited.

Classify decisions by cost of reversal. Naming, payload shape, public API semantics, data ownership, partition keys, and externally visible consistency can be costly to change. Instance sizes and many internal libraries are easier to replace. Spend review time accordingly.

Decision Current reason Revisit when
One primary link store Current write rate and data size fit tested limits Storage, write rate, maintenance, or recovery approaches a limit
Asynchronous analytics Analytics is not required for redirect correctness A product contract requires real-time exact counts
Bounded cache staleness Fast redirects with a 60-second disable guarantee Safety policy requires immediate global revocation
Single-region write ownership Simpler correctness and current recovery target Regional write availability or latency becomes a hard requirement

17. Common mistakes and corrections

Mistake Why it fails Correction
Starting with a technology list The design has no workload or requirement argument Clarify flows, targets, and estimates first
Using only daily averages Peaks and failure capacity determine saturation Model normal peak, failure peak, events, and recovery
Giving one exact capacity number Inputs are uncertain and distributions matter Use ranges, headroom, sensitivity analysis, and measurements
Treating p99 as a maximum One percent of requests are slower Define timeout, failure, and extreme-tail behavior
Calling replicas highly available They may share fate or lack remaining capacity Map fault domains and test the intended loss
Ignoring dependency objectives A hard dependency can consume the service budget Align objectives, remove hard paths, and design degradation
Equating durability with backup Untested backups may be incomplete or too slow to restore Define RPO and RTO and perform restore tests
Adding cache, queue, or microservices automatically Each adds failure modes and operational cost Add a component only for a named requirement or bottleneck
Designing only the happy path Partial and slow failures dominate distributed incidents Write failure timelines and degraded behavior
Claiming infinite scale Every design has finite resources and coordination points Name the next bottleneck and its review trigger

18. Practice exercises

  1. A service receives 120 million requests per day with a six-times peak factor. Calculate average and peak requests per second. Add 40% headroom.
  2. Peak traffic is 50,000 requests per second and average latency is 240 ms. Estimate in-flight concurrency. Recalculate at 1.5 seconds during overload and explain the operational effect.
  3. Design SLIs and SLOs for redirect, creation, disable, and analytics flows. State which failures count and where measurements are taken.
  4. Estimate five-year storage for 20 million 800-byte records per month with three replicas, 60% index overhead, and 30% headroom.
  5. Draw a context, data-flow, sequence, and deployment diagram for the URL shortener. Explain the different question each diagram answers.
  6. Remove the cache, primary store, one zone, event buffer, and identity provider one at a time. Define user behavior, protection, signals, mitigation, and recovery.
  7. The product changes link-disable propagation from 60 seconds to one second. Identify every design, cost, capacity, and operational decision that must be revisited.
  8. Write an ADR comparing random short codes with allocated numeric IDs encoded as base 62.
  9. Create a load-test plan that finds sustainable capacity and the failure mode beyond saturation.
  10. Review a design that uses ten services, three databases, two queues, and a cache for 100 requests per minute. Identify unnecessary complexity and propose a simpler baseline.

19. Interview questions and model answers

1. Functional versus non-functional requirements?

Functional requirements describe capabilities and state changes, such as creating and resolving a short link. Non-functional requirements describe qualities and constraints, such as p99 latency, availability, durability, privacy, and cost. The distinction helps select architecture, but both must be testable.

2. Why estimate before choosing components?

Estimates reveal the order of magnitude and workload shape. A design for 100 requests per second and 10 GB differs from one for 100,000 requests per second and 10 PB. Estimates also expose whether the main problem is compute, storage, bandwidth, concurrency, or operational complexity.

3. Why is average requests per second insufficient?

Capacity is consumed during peaks, failures, deployments, retries, and recovery. An average hides bursts and uneven distributions. Model normal peak, failure peak, exceptional events, and backlog recovery, then validate with real traffic.

4. How does Little's Law help?

For a stable system, average in-flight work equals arrival rate multiplied by average time in the system. It connects throughput and latency to concurrency. If latency rises while arrivals remain, in-flight work grows and can exhaust bounded resources.

5. Why use latency percentiles?

Latency distributions are normally skewed. A mean can remain acceptable while a meaningful fraction of users is very slow. p50 describes typical behavior, while p95, p99, and p99.9 reveal different parts of the tail. Always state population, location, and window.

6. SLI versus SLO versus SLA?

An SLI is the measured behavior. An SLO is the target for that measurement. An SLA is a business or contractual commitment with consequences. Teams usually operate to an internal SLO stricter than the public SLA.

7. What is an error budget?

It is the amount of unreliability allowed by an SLO. A 99.9% success SLO permits 0.1% unsuccessful events in the window. Teams use budget consumption to balance release velocity and reliability work.

8. Availability versus durability?

Availability means the service can be used now. Durability means acknowledged data remains intact. A system can be unavailable while data is safe, or available while returning data that will later be lost.

9. Why not always require more availability nines?

Each additional nine reduces the error budget and demands more isolation, redundancy, automation, testing, and spare capacity. It can slow delivery and increase cost. The target should follow user harm and business need.

10. What is a critical path?

It is the sequence of work and dependencies that must succeed for a critical operation to complete. Optional work should be removed from it when possible. Every hard dependency adds latency and failure exposure.

11. What is a single point of failure?

Any one failure whose loss makes the required service unavailable or incorrect. It can be a process, data store, zone, network path, certificate, deployment, control plane, or human procedure. Multiple replicas are not independent when they share the same failure.

12. Why keep headroom?

Headroom absorbs normal peaks, forecast error, deployments, retries, zone loss, cache warming, and recovery work. It should be tied to a failure and growth model, not chosen as an unexplained percentage.

13. Scalability versus performance?

Performance describes behavior at a particular load and resource level. Scalability describes how performance or throughput changes as load and resources change. A fast single instance may scale poorly because of shared locks or centralized state.

14. Why identify state early?

State determines ownership, consistency, durability, recovery, migration, and scaling boundaries. Stateless compute is easy to replace, while state movement and coordination are usually the hard parts of system evolution.

15. What belongs in an ADR?

Context, constraints, decision, alternatives, positive and negative consequences, safeguards, and review triggers. It records why the decision made sense at the time without pretending it is permanent.

16. How do you find a bottleneck?

Trace the critical path, estimate demand per resource, measure utilization, wait time, queue depth, and throughput, then increase load until useful throughput stops scaling or latency rises sharply. The saturated resource or coordination point is the current bottleneck.

17. How should a system-design interview begin?

Clarify users, must-have flows, scale, quality targets, constraints, and exclusions. State assumptions, estimate the workload, sketch a simple correct design, then deep-dive the largest risks and trade-offs.

18. Why start simple?

Simplicity reduces failure modes, cost, and cognitive load. It establishes a correct baseline and makes each later component answer a named need. Premature distribution can make ordinary correctness and operations much harder.

19. How do you validate a paper design?

Turn assumptions into tests and measurements: representative integration tests, production-shaped load, stress beyond saturation, fault injection, long-running soak tests, restore drills, security tests, and SLO monitoring.

20. What makes a trade-off explanation strong?

It names the requirement being optimized, credible alternatives, costs accepted, risks introduced, safeguards, and the condition that would trigger reevaluation. "Technology X scales" is not enough.

20. Concise cheat sheet

  • Requirements first, estimates second, components third.
  • Separate must-have functions from optional scope.
  • Make latency, availability, durability, consistency, security, and cost measurable.
  • Average RPS equals daily requests divided by 86,400.
  • Concurrency is approximately arrival rate multiplied by time in system.
  • Model normal peak, failure peak, exceptional events, and recovery load.
  • Storage includes data, metadata, indexes, logs, replicas, backups, migration space, and headroom.
  • Use percentiles for skewed latency, and state the population and window.
  • An SLI is a measurement, an SLO is a target, and an SLA is a commitment.
  • Error budget is the allowed unreliability implied by the SLO.
  • Availability, reliability, durability, recoverability, and resilience are different.
  • Every hard dependency adds latency and failure exposure to a critical path.
  • Replicas need independent failure domains and enough remaining capacity.
  • Draw context, data-flow, sequence, deployment, and state diagrams for different questions.
  • Record costly decisions and review triggers in ADRs.
  • Name the next bottleneck. No real system scales infinitely.
  • Test the claims: capacity, overload, fault behavior, and recovery.
  • A good design explains why, what it sacrifices, and when it must change.

21. Official references

Last reviewed · July 2026 · part of knowledge-base