System Design Fundamentals
Trade-Offs in System Design
Imagine a payment checkout and an Instagram like count both need to "scale." One must never show the wrong balance. The other can be off by a few likes for a second. Same industry buzzwords, opposite acceptable risk.
A trade-off means improving one quality usually costs another. Senior answers compare options and say what you gain and what you accept, not just which database brand sounds advanced.
Decision loop
Requirement
Is wrong data dangerous, or only ?
Options
Name at least two credible paths.
Choice
Pick for , volume, or correctness.
Cost + mitigation
Name the downside and how you watch it.
What actually happens in a good answer
Beginners often answer with a single technology ("we'll use a wide-column store"). Stronger answers start from the user requirement: Is wrong data dangerous, or only annoying? Is the pain , missed writes, or cost?
Then they compare levers. A cache can improve read speed but reduce unless and invalidation are intentional. Stronger can protect money paths but may hurt during partitions. Batching can raise while adding wait time.
The finishing move is the risk sentence: what you accept, how you mitigate it, and which metric proves the choice still fits, including promises and when consumers fall behind.
Try it: pick a lever and name the downside
Trade-offs start from the user promise, not from a favorite database. Choose a scenario, commit to option A or B, and read how latency, freshness, cost, and availability shift.
Reads dominate; slightly stale ranking is acceptable for most users.
Aggressive cache + eventual ranking
Optimize p95 read latency; accept brief staleness.
Strong consistency on every read
Every read reflects the latest write; higher latency and DB load.
Quality bars appear after you commit to an option.
- Scenario
- Home feed reads
- Decision
- Not chosen
Pick a product scenario, then choose an architecture leaning. Compare quality bars and practice the risk sentence for the option you did not pick.
Finish with a risk sentence. Strong answers sound like: "We accept brief staleness on feeds and prove freshness with sampling; we do not accept that on ledger writes."
With that loop in mind, here is how to choose under interview pressure without memorizing a catalog of databases.
How to choose under pressure
1. Is stale data dangerous? Payments, inventory, and auth lean strong . Like counts, feed rankings, and analytics often tolerate short staleness (same tension as the checkout vs likes story above).
2. Is the pain or volume? Optimize latency for interactive paths; optimize for batch pipelines and fan-out workers, and say which one you chose.
3. Can you name the metric? Hit ratio, queue age, replication lag, and p95 latency turn a vague trade-off into an operable decision.
Simple rule of thumb
Never present a component without its cost. If you add a cache, say the you accept. If you add a queue, say the completion delay you accept. That one sentence is what makes the answer sound senior.
The same three questions become a reusable loop you can draw on the whiteboard in under a minute.
Trade-off decision loop
A useful comparison holds the workload and required guarantees constant. Compare two ways to serve the same profile page: reading the database on every request, or caching the result for 30 seconds. The cache saves repeated queries but creates a period during which an edit may not appear. Decide whether that delay is acceptable, how the editing user sees their own change, and what happens when the cache is empty. Without a shared scenario, “fast” and “consistent” remain vague labels.
The mistake is treating trade-offs as a list to memorize. Start from a requirement, compare at least two options, choose one for this scenario, then name the risk and mitigation.
Requirement
Options
Choice
Cost accepted
Mitigation and metric
Follow-up ready
Reusable sentence pattern
"Given requirement X, I am choosing A over B. We gain Y, but accept Z; I would monitor M and mitigate with N."
How to use this pattern
- Interview: When you pick a store or cache policy, name one clear downside you accept.
- On the job: Document assumptions so teammates know the freshness bar.
Once the loop is clear, the next step is seeing how one product changes when the binding constraint changes.
Same problem, different constraint
A notification system can look very different under each constraint. Scan the matrix below when you need a quick "improves / worsens / metric" template for cache or queue choices.
| Constraint | Design move |
|---|---|
| Strict correctness | Deduplicate sends, store audit log, accept higher . |
| Low latency | Use cache and async fanout, accept eventual delivery status. |
| Low cost | Batch work and reduce replicas, accept slower peak handling. |
| Fast delivery | Keep one simple service, accept limited scale for now. |
| Global | Replicate by region, accept consistency and cost complexity. |
Trade-off matrix template
| Option | Improves | Worsens | Choose when | Metric | Failure mode |
|---|---|---|---|---|---|
| Cache | Read latency | Freshness | Reads repeat often | Hit ratio | Stale or missing data |
| Queue | Resilience | Completion latency | Work can finish later | Oldest message age | Backlog and duplicates |
Vocabulary that sounds precise
Instead of saying "this scales," name which quality improves and which gets worse. Keep these words near every architecture choice.
- : how old returned data can be before users suffer.
- : can acknowledged writes survive disk or zone loss?
- Blast radius: how many users fail when one component breaks?
- Saturation: which resource hits its limit first under load?
- : how producers slow when consumers fall behind.
- Operational cost: who runs, debugs, pages, migrates, and pays?
Interview sentence: "The bottleneck is not API CPU; it is write amplification in the storage layer. I would reduce fanout, batch work, and monitor queue age plus p95 write latency."
The classic interview pair is consistency versus availability. The next section makes that choice concrete without repeating the checkout story.
Consistency vs availability
Be precise about which operation needs which guarantee. A checkout service may serve an old product description during a network problem but must coordinate the last unit of stock before confirming its sale. One product can therefore use different consistency policies on different paths. Strong consistency here means a defined ordering guarantee such as linearizability, not simply that replicas normally catch up quickly.
(in interview speak) often means every reader sees the latest write quickly. means the system keeps answering even when parts fail. When networks glitch between replicas, designs force a choice: wait for agreement (stronger consistency, risk timeouts) or respond from the best local copy (more availability, risk staleness). Neither is morally superior; it depends on whether wrong data is dangerous or merely annoying (see the hero checkout vs likes framing).
| Mode | Behavior | Choose when | Cost |
|---|---|---|---|
| Strong consistency | Every read returns the most recent write | Bank transfers, inventory, leader election, auth tokens | Higher latency; lower availability during partitions |
| Eventual consistency | Reads may return stale data temporarily | Social feeds, likes, analytics, search indices, CDN content | App must handle stale reads for speed |
| System | Choice | Details |
|---|---|---|
| Globally consistent SQL store | Strong | Synchronized clocks, higher write coordination cost |
| Managed key-value store | Eventual | Default eventual, stronger reads cost more |
| Social graph cache | Eventual | Very high cache hit ratio, seconds of staleness OK |
| Bank transfers | Strong | Cannot show wrong balance |
| Social likes | Eventual | Off by 3 for a second? Fine |
Even when correctness is settled, you still choose between time-to-one-request and work-per-second.
Latency vs throughput
Suppose each database batch has 5 milliseconds of fixed overhead plus 1 millisecond per item. Processing one item at a time takes 6 milliseconds per item, about 167 items per second for one serial worker. A batch of ten takes 15 milliseconds, about 667 items per second, but the first item may wait for nine more to arrive. A maximum batch age bounds that waiting time while a maximum batch size bounds memory and transaction work.
is how long one unit of work waits; is how many units finish per second. Optimizing for one often hurts the other. Batching increases throughput but adds latency because items wait to fill a batch. Highly parallel pipelines raise throughput but add coordination overhead and can hurt tail latency if one stage stalls.
| Focus | Typical moves |
|---|---|
| Latency-optimized | Process immediately, in-memory cache (~1ms), edge/CDN (5-20ms), connection pooling |
| Throughput-optimized | Batch requests (100ms linger), bulk DB writes (10K rows), async queues, columnar scans (Parquet) |
Concrete linger timings and the cost/latency ladders live in Numbers to know below.
Example: Queue Producer
linger.ms=0 → 1 msg/request, lowest latency, poor throughput
linger.ms=100 → batch 100ms of msgs, 10x throughput, +100ms latencyDistributed-database interviews often package the same tension as CAP and PACELC language.
CAP and PACELC theorems
CAP is a teaching lens for distributed databases, not a literal dipstick you hold against every microservice. Most real systems blend patterns: sync writes to a primary, async replicas, caching layers with . Still, interviewers expect CAP/PACELC language when comparing highly available stores vs strongly consistent SQL.
CAP & PACELC Theorems
CAP THEOREM:
In a distributed system during a network partition (P), you must choose between Consistency (C) and Availability (A).
CP Systems: Refuse requests if unsure of consistency → coordination stores, strongly consistent databases
AP Systems: Always respond, even with potentially stale data → wide-column stores, key-value stores, DNS
PACELC extends CAP:
If Partition → choose A or C. Else (normal operation) → choose Latency or Consistency.| PACELC | Systems | Trade-off |
|---|---|---|
| PA/EL | Key-value / wide-column stores | Available + low latency, sacrifice consistency |
| PC/EC | Strongly consistent SQL stores | Consistent always, pay latency cost |
| PA/EC | Document stores with tunable reads | Available during partition, consistent otherwise |
- CP coordination store: refuses writes without quorum so cluster metadata stays correct.
- AP wide-column store: stays writable with tunable ONE/QUORUM/ALL consistency levels.
- PA/EC document store: serves secondary reads in partitions; primary reads stay consistent.
Before you pick a more expensive architecture, put the performance and QPS math in one place and reuse it.
Numbers to know
Rough orders-of-magnitude illustration: each row buys more performance but raises monthly bill and operational surface area. Translate this to your cloud pricing reality; the ratios matter more than exact dollars. Later sections should cross-reference this block instead of restating these figures.
| Approach | Performance | Monthly Cost (1B requests) |
|---|---|---|
| Single VM + SQLite | 10 req/s | $50 |
| Managed relational DB | 5K req/s | $2,000 |
| In-memory cache layer | 100K req/s | $5,000 |
| Multi-AZ + replicas | 500K req/s | $20,000 |
| Global CDN + edge | 1M+ req/s | $50,000+ |
Diminishing returns
- First ~$1K often buys ~100x via caching before replicas and edge spend.
- Next ~$10K often buys ~10x via replicas and CDN before edge polish.
- Next ~$50K often buys ~2x via edge tuning after the easy wins.
Micro-calculations
- Cache hit ratio: 10,000 read QPS at 90% leaves 1,000 database QPS; at 50% it becomes 5,000.
- Batching 100 writes raises , but a 100 ms wait adds visible .
- Nearby regions lower read latency; sync cross-region writes add coordination delay and cost.
Quantitative drills
Drill 1: cache
A profile service does 12K read QPS and 300 write QPS. A 95% cache hit ratio leaves 600 database read QPS. If a shorter TTL drops hit ratio to 80%, the database suddenly absorbs 2.4K read QPS. Is the extra worth 1.8K more database QPS?
Drill 2: sync vs async writes
A checkout path calls a fraud provider with p95 = 180 ms and retries can double that. If your end-to-end budget is 250 ms, synchronous calls consume most of the user-visible time budget. Which checks stay inline, and which move to asynchronous review?
Drill 3: multi-region writes
Regional write latency is 12 ms, but cross-region synchronous quorum raises commit latency to 95 ms. That may be worth it for money movement, but not for likes or view counts. What correctness guarantee justifies the extra 83 ms?
Caching size and extremes
- TTL too short: low hit rate overloads the database under repeated reads.
- TTL too long: users see stale data longer than the product can accept.
- Cache too small: constant evictions thrash memory and waste fetch work.
- Cache too big: wasted memory raises cost without matching hit-ratio gains.
With the numbers parked above, the remaining levers are how you shape reads, writes, caches, and early-stage simplicity.
Design levers: reads, writes, caches, and stage
Trade-off triangles
Many choices pull three qualities against each other. Pick the two that matter most and explain the third cost.
Consistency
Availability
Latency
Pick two; the third is the cost
Cost
Reliability
Complexity
Pick two; the third is the cost
Freshness
Speed
Write cost
Pick two; the third is the cost
Read vs write optimization
An index is a concrete example of moving cost between paths. It lets a read jump to matching rows, but every insert or indexed-field update must also maintain the index. A precomputed feed goes further: each new post may update hundreds of followers’ feed entries, making later feed reads cheap. If most followers never open the app, much of that write work is wasted. Estimate both useful reads and amplified writes before choosing precomputation.
Read-optimized systems
- Denormalization stores data redundantly so hot reads avoid joins.
- Materialized views precompute results so dashboards stay cheap.
- Heavy caching (CDN + shared + in-process) cuts repeated read latency.
- Read replicas help when read:write ratios approach about 10:1.
- CQRS separates read and write models when shapes diverge sharply.
Example: social timeline fan-out on write precomputes feeds into cache so reads become O(1) lookups.
Write-optimized systems
- LSM trees in write-optimized stores absorb appends with less random I/O.
- Append-only logs and event sourcing keep writes sequential and durable.
- Write-behind caching buffers then batch-flushes to protect write paths.
- Normalized schemas keep a single write location when consistency matters.
- Async replication avoids waiting on every replica before acknowledging.
Example: ride matching at 1M+ location updates/sec appends to a log, then indexes asynchronously.
Caching strategy comparison
TTL extremes and hit-ratio math are in Numbers to know; this table compares freshness versus complexity.
| Strategy | Freshness | Complexity |
|---|---|---|
| TTL-based | Stale window guaranteed | Simple |
| Event-based | Fresh | Complex CDC pipeline needed |
| Write-through | Always fresh | Slower writes |
| Hybrid | Event-based + TTL safety net | Moderate |
Simplicity vs scalability
Start simple
A monolith can serve a large user base when its workload fits available compute and storage capacity; there is no universal user-count limit. A single well-tuned relational database can handle high TPS. Vertical scaling is underrated: one large machine handles more than most startups need.
Scale when forced
Microservices, sharding, and CQRS add coordination, deployment, and recovery work; the increase depends on the workload and organization, not a fixed multiplier. Large platforms may run 1000+ microservices because they also have large teams to manage them. Premature optimization is costly early; at billion-user scale, many of those optimizations become justified.
Close the chapter by packing interview practice, an ADR template, and sources into one wrap-up instead of a stack of cards.
Wrap-up
Every design decision is a trade-off
At billion-user scale, there are no perfect solutions, only choices with side effects. Large marketplaces have measured that extra latency hurts revenue; large search products have reported latency hurting usage. Those stories are reminders that engineering decisions affect users and dollars, not arguments that your weekend project needs global CDN edge POPs on day one. Pick trade-offs that match your stage: MVP, growth, or hyperscale (cost ladders in Numbers to know).
Lightweight ADR pattern for interviews
Record the condition that would make you revisit the decision. “Use a cache” is incomplete; “cache public profiles for 30 seconds while the database can survive the measured miss rate; revisit if edit visibility or miss traffic breaches its target” is reviewable. This prevents a reasonable early choice from becoming an unexplained permanent constraint. The same record should include the fallback if the new component fails.
When the discussion gets fuzzy, state the decision as a mini ADR (Architecture Decision Record) so the trade-off is explicit.
Decision:
Use cache-aside with 60s TTL for product reads.
Context:
Reads are 20x writes and p95 latency matters more than perfectly fresh inventory counts.
Alternatives considered:
1. Direct DB reads only
2. Write-through cache
Why this choice:
Cache-aside cuts read latency and DB load immediately.
Accepted cost:
Users may see stale data for up to 60s.
Mitigation and metric:
Invalidate on critical writes; monitor hit ratio, stale-read complaints, and DB read QPS.Common interview trade-off questions
| Question | Key Trade-Off |
|---|---|
| SQL vs NoSQL? | Schema flexibility vs query power |
| Microservices vs monolith? | Team autonomy vs operational cost |
| Push vs pull notifications? | Latency vs resource efficiency |
| Sync vs async communication? | Simplicity vs resilience |
| Cache vs no cache? | Speed vs freshness |
| Normalize vs denormalize? | Write efficiency vs read speed |
| Single leader vs multi-leader? | Consistency vs write availability |
| Batch vs stream processing? | Throughput vs latency |
| Strong vs eventual consistency? | Correctness vs performance |
- State both sides clearly so the interviewer hears a real comparison.
- Explain when each option is preferred for the stated requirements.
- Give one concrete example for each side without inventing new products.
- Recommend one choice for this scenario and name the accepted cost.
- Mention the metric you would monitor to validate the choice still fits.
Design decision drills: why not the alternative?
- Storage: Why relational database over key-value store for orders?
- Cache: Why cache-aside instead of write-through for profiles?
- Queue: Why async queue instead of synchronous provider call?
- API: Why cursor pagination instead of offset pagination?
- Consistency: Why eventual for likes but strong for balances?
Interview tip
Never present a single solution. Always discuss at least two approaches with their trade-offs, using the reusable sentence in the decision loop above. Reason about trade-offs at every layer, from database choice to caching strategy to API design.
Primary sources
- Brewer: CAP Twelve Years Later: trade-offs under partition.
- Abadi: PACELC: latency vs consistency when healthy.
- Google SRE: Embracing Risk: error budgets as explicit trade-offs.
Practice and further reading
Use these exercises to connect the lesson to a design decision. State your assumptions, trace what happens to one request, and explain the rule that must remain true even during a failure. That rule is the design's correctness invariant.
Focus for this lesson: Compare options against workload, consistency, latency, operability, cost, and reversibility instead of declaring a universally best technology.
Explain the decision
Give a strong trade-off statement for adding a cache.
Read the reasoning
A cache lowers read latency and database load, but introduces staleness, invalidation, stampede, and memory cost; choose it only with an explicit freshness contract.
Apply it to a production scenario
A feed can return in 80 ms from stale replicas or 450 ms from the primary. What do you choose?
Read one approach
Segment fields by consistency need, use bounded-staleness replicas for feed content, and route privacy/deletion checks through a fresher authority.
Work through the numbers
A cache improves p95 from 220 ms to 35 ms at 92% hit rate. Estimate average latency if misses still cost 220 ms.
Read the worked calculation
0.92 × 35 + 0.08 × 220 = 49.8 ms, excluding lookup overhead and tail effects.
Reason through a failure
What must an Architecture Decision Record capture for a hard-to-reverse choice?
Read the recovery reasoning
Context, decision, alternatives, measurable consequences, rollback constraints, owner, and the signal/date that should trigger reconsideration.
Sources and further study
Continue with Interview Framework & Rubric.