StackPractices
advanced By Mathias Paulenko

System Design Interview: Framework, Examples & Practice

A practical framework for system design interviews: how to structure your answer, the concepts interviewers actually probe, and two worked examples with real numbers.

Introduction

Most candidates who fail a system design interview don’t fail because they lack knowledge. They fail because they start drawing boxes before asking a single question, or because they recite technology names without explaining why those technologies fit the problem in front of them.

System design interviews evaluate your ability to reason about ambiguous, open-ended problems. There’s no correct answer waiting at the end; there’s a conversation the interviewer uses to observe how you scope, decompose, quantify, and defend decisions. This guide gives you a repeatable structure for that conversation, the core concepts you’re expected to explain fluently, and two worked examples with real numbers.

What the Interviewer Is Actually Scoring

Before learning frameworks, it helps to know what is being evaluated. Rubrics vary by company, but they almost always cover the same five dimensions:

  • Problem discovery. Did you clarify requirements and constraints before designing? Seniors ask “how many users?” before drawing anything; juniors start drawing immediately.
  • Structured reasoning. Did you decompose the problem into components and attack them in a sensible order, or did you jump randomly between topics?
  • Trade-off analysis. Every decision has a cost. “We use a relational database” earns few points; “we use a relational database because we need transactional integrity for payments, at the cost of harder horizontal scaling” is what interviewers listen for.
  • Quantitative thinking. Can you convert “very popular” into requests per second, gigabytes per day, and cache hit rates? Back-of-the-envelope math separates seniors from juniors faster than any buzzword.
  • Communication. Do you narrate your reasoning, check in with the interviewer, and treat their hints as requirements? Think of it as pair-designing with a colleague, not defending a thesis.

Two signals matter more than the rest: asking clarifying questions first and stating assumptions explicitly. Interviewers forgive missing knowledge; they rarely forgive designing the wrong system confidently.

The 4S Framework

A reliable answer follows four phases: Scope, Sketch, Scale, Solidify. The framework exists to prevent the two most common failure modes — solving the wrong problem and running out of time in the middle of the interesting part.

flowchart diagram: Scope<br/>clarify + quantify<br/>2-3 min

1. Scope (2-3 minutes)

Clarify requirements before designing anything. Write them on the board so the interviewer can correct you early — a corrected assumption at minute three costs nothing; a wrong assumption discovered at minute thirty costs the interview.

Functional requirements:

  • What capabilities must the system support?
  • What are the core use cases, and which are out of scope?

Non-functional requirements:

  • Scale: how many users? Requests per second? Read-to-write ratio?
  • Latency: what is an acceptable response time?
  • Availability: what uptime is required — 99.9% or 99.99%?
  • Consistency: can reads tolerate eventual consistency, or must they be strong?

Example: for “design a URL shortener like bit.ly”, a good scoping pass produces:

  • Functional: shorten a URL, redirect, custom aliases, click analytics.
  • Scale: 100M new URLs/day, 10B redirects/day — a 100:1 read-to-write ratio.
  • Latency: under 50 ms for redirects.
  • Availability: 99.99%, because redirects are on the critical path of the product.

That scoping output already implies the architecture: read-heavy means aggressive caching; 100:1 means the write path can be slower than the read path; analytics means an async pipeline, not synchronous writes.

2. Sketch (10-15 minutes)

Draw a high-level design with the major components, and narrate each box as you draw it. The sketch doesn’t need to be right — it needs to be a baseline the interviewer can react to.

flowchart diagram: Client --> CDN[CDN / edge cache

The components worth knowing cold:

  • Load balancer: distributes traffic across servers (round-robin, least connections).
  • API gateway: authentication, rate limiting, routing at the edge.
  • Application servers: stateless so they scale horizontally without coordination.
  • Cache: Redis or Memcached for hot data; read replicas for hot queries.
  • Database: SQL vs. NoSQL is itself a trade-off question — see how to choose.
  • Message queue: Kafka or RabbitMQ to decouple slow or bursty work.
  • CDN: static assets and edge caching close to users.
  • Object storage: S3-style stores for files and media.

Resist naming vendors in the sketch (“object storage” instead of “S3”). It signals you think in roles, not in product brochures.

3. Scale (10-15 minutes)

Now name the bottlenecks yourself — before the interviewer points at them — and remove them in order of impact. A useful habit: for every bottleneck you name, say how you would detect it (“our p99 read latency would climb” or “write throughput would saturate the primary”).

BottleneckFirst-line solution
Read-heavy trafficCache + CDN + read replicas
Write-heavy trafficSharding + message queues
Single point of failureMulti-AZ deployment, replication, failover
Slow queriesIndexes, denormalization, dedicated search indexes
Large file storageObject storage + presigned URLs

Back-of-the-envelope math. Say the numbers out loud as you compute them; interviewers evaluate the process, not the arithmetic:

100M URLs/day  ≈ 1,160 writes/s   (peak ~3,000/s)
10B reads/day  ≈ 115,000 reads/s  (peak ~300,000/s)

URL record: short_code (6 B) + long_url (500 B) + metadata (100 B) ≈ 600 B

Storage: 100M × 600 B ≈ 60 GB/day ≈ 22 TB/year

Numbers like these justify decisions: 60 GB/day is small enough that a single primary handles writes for years; 300k reads/s isn’t, so the read path needs a cache absorbing 95%+ of traffic.

4. Solidify (5-10 minutes)

Close by covering what happens when reality interferes:

  • Monitoring: latency percentiles, error rate, cache hit rate, queue depth.
  • Security: rate limiting, input validation, abuse detection.
  • Data retention: archival policy, deletion requests (GDPR).
  • Disaster recovery: backups, point-in-time recovery, RPO/RTO targets.

If time remains, proactively name the weakness of your own design — “this schema works until one URL goes viral, at which point the cache key becomes a hot spot” is a stronger ending than any diagram.

Core Concepts Worth Explaining Well

Horizontal vs. Vertical Scaling

VerticalHorizontal
ApproachBigger machineMore machines
LimitHardware ceilingNear-unlimited
CostExpensive per unitCheaper per unit at scale
DowntimeUsually requires someRolling deploys, no downtime
ComplexitySimpleRequires load balancing and distributed state

The answer interviewers want isn’t “always scale horizontally” — it’s “scale vertically until the complexity of distribution is justified.” A primary database often stays vertical longer than anything else in the system precisely because distributed state is expensive.

Database Sharding

Sharding partitions data across database nodes so no single one holds the whole load:

Shard by user_id % 4:
  User 1 → Shard 0     User 4 → Shard 3
  User 2 → Shard 1     User 5 → Shard 0
  User 3 → Shard 2

Choosing the shard key is the real interview question. A good shard key has high cardinality (many distinct values), produces even distribution (no hotspots when one key is a celebrity with 100M followers), and matches the dominant query pattern (query locality — most queries include the key). Mention resharding: changing the key later is painful, so pick it for where the system will be, not where it’s today. For the full treatment, see the complete guide to database sharding.

Caching Strategies

StrategyHow it worksUse case
Cache-asideApp checks cache, loads from DB on missRead-heavy; app controls logic
Read-throughCache fetches from DB transparentlySimpler application logic
Write-throughWrites update cache and DB togetherStrong consistency on reads
Write-behindWrites go to cache, flush to DB asyncWrite-heavy; tolerates delay

Two follow-ups interviewers love: cache stampedes (when a hot key expires and thousands of requests hit the database simultaneously — mitigated by locking or early recompute) and invalidation (deciding when cached data is stale — TTLs, explicit purge on write, or versioned keys). The full playbook is in the caching strategies recipe.

The CAP Theorem — and What Comes After It

In a distributed system you can only guarantee two of three properties:

  • Consistency: all nodes see the same data at the same time.
  • Availability: every request receives a response.
  • Partition tolerance: the system keeps working despite network failures.

The practical version: partitions aren’t optional, so the real choice is CP or AP during a partition. PACELC extends this further — if partitioned, choose availability or consistency; else, choose latency or consistency. That second clause is where most real trade-offs live: even without a partition, stronger consistency costs round-trips. The CAP theorem guide covers PACELC and per-system tuning in depth.

Worked Example: Design a URL Shortener

This is the canonical interview problem, and it’s worth rehearsing end to end. Requirements from the scoping phase: shorten URLs, redirect fast, support custom aliases, collect click analytics. 100M writes/day, 10B reads/day, <50 ms redirects, 99.99% availability.

Step 1 — Capacity estimation. The math from the Scope phase gives ~1,160 writes/s and ~115,000 reads/s. Storage works out to roughly 60 GB/day and ~21 TB/year — small enough that capacity planning is about read throughput, not disk.

Step 2 — API design. Three endpoints cover the contract:

POST /api/v1/shorten
  Body:     { "url": "https://example.com/...", "custom_alias": "my-link" }
  Response: { "short_url": "https://s.io/my-link", "code": "my-link" }

GET /:code
  Response: 301 redirect to long_url
  Headers:  Cache-Control: public, max-age=31536000

GET /api/v1/stats/:code
  Response: { "clicks": 12345, "unique_visitors": 8900 }

The 301 with a long cache lifetime is deliberate: permanent redirects are cacheable at the CDN edge, which removes load before it ever reaches the application.

Step 3 — Short code generation. Three options, each with a real trade-off:

  • Base62 of an auto-increment ID. No collisions and sortable, but predictable — anyone can enumerate every shortened URL. Fix it by XOR-ing the ID with a secret, or accept enumeration as a non-goal.
  • Hash + truncate. Take the first 7 base62 characters of MD5(long_url). The same URL yields the same code (deduplication for free), but you need retry logic on collisions.
  • Distributed ID (Snowflake-style). A 64-bit timestamp + worker + sequence ID needs no coordination and has no collisions, at the cost of longer codes.

A defensible choice: auto-increment with XOR obfuscation — simple, collision-free, non-enumerable.

Step 4 — Data model. Split the workload by access pattern rather than forcing one engine to do everything:

-- PostgreSQL: URL mappings (OLTP, low write volume)
CREATE TABLE url_mappings (
    short_code VARCHAR(7) PRIMARY KEY,
    long_url   TEXT NOT NULL,
    user_id    BIGINT,
    created_at TIMESTAMP DEFAULT now(),
    expires_at TIMESTAMP
);

-- Cassandra: click events (write-heavy analytics)
CREATE TABLE click_events (
    short_code text,
    clicked_at timestamp,
    ip_address text,
    user_agent text,
    referrer   text,
    PRIMARY KEY (short_code, clicked_at)
) WITH CLUSTERING ORDER BY (clicked_at DESC);

Click events are append-only, high-volume, and queried per code — a wide-column store’s ideal workload. The URL map is small, relational, and read through the cache anyway.

Step 5 — Architecture. The assembled design:

flowchart diagram: Client --> CDN[CDN<br/>edge redirect cache

Step 6 — Caching strategy. Redis maps short_code → long_url with a 24-hour TTL; the CDN caches the 301 response itself. Target a >95% cache hit rate so only ~5% of reads reach PostgreSQL. On URL update or expiry, delete the Redis key and purge the CDN entry.

Step 7 — Sharding (when it becomes necessary). At ~3,000 peak writes/s a single primary is comfortable for years; sharding is a year-two concern. When it arrives, shard by hash(short_code) — that’s the key every read already carries. Sixteen shards with three read replicas each push read capacity to ~320k reads/s with headroom.

Step 8 — Operational concerns. Alert on p99 redirect latency above 100 ms, cache hit rate below 90%, and error rate above 0.1%. PostgreSQL gets point-in-time recovery; the design’s RPO is under a minute and RTO under fifteen minutes with multi-AZ standby.

A Second Example: Design a Chat System

The chat system probes different muscles than the URL shortener — real-time delivery and ordering instead of cache economics — which is why interviewers use it to test whether you actually understand the first example or just memorized it.

The scoping questions reveal the real problem: 1:1 or group chat? Online presence? Message history and search? Delivery guarantees? A “simple” chat app at scale is really three systems — a message pipeline, a presence service, and a history store.

Trade-offs to name out loud as you sketch:

  • Real-time delivery: persistent WebSocket connections vs. long polling. At scale you shard connections by user and route messages through a pub/sub layer; the real-time WebSockets recipe covers the mechanics.
  • Message ordering: no global clock exists, so you order per conversation — a conversation-scoped sequence number or lamport clock.
  • Fan-out: for group chats, decide per group size whether you push to every member’s inbox eagerly or let members pull — the same push-vs-pull trade-off as a feed’s fan-out.
  • Storage: recent messages in a fast store keyed by conversation; history in a cheaper store partitioned by conversation and time.

If you can contrast this case with the URL shortener — “here reads are cheap but delivery semantics are hard; there delivery was trivial but read volume dominated” — you’re demonstrating reasoning transfer, which is the actual skill being graded.

Expectations by Level

Interviewers calibrate difficulty to the level of the role:

LevelWhat is expected
JuniorStructured approach, basic components, willingness to ask questions. Depth in one or two areas is enough.
Mid-levelCorrect trade-off vocabulary, capacity math without prompting, one complete design end to end.
SeniorDrives the interview proactively, quantifies every claim, discusses failure modes unprompted.
Staff+Designs for evolution: data model changes, multi-region, organizational constraints, cost. Mentions what they would not build yet.

The single biggest level signal is whether you optimize for the stated scale or for imaginary scale. A junior answer designs for a billion users; a staff answer designs for 100M and says exactly where it breaks.

Managing the 45 Minutes

A time budget that survives contact with a real interview:

PhaseBudgetWhat “done” looks like
Scope2-3 minRequirements written down, assumptions stated
Sketch10-15 minComponents on the board, data flow narrated
Scale10-15 minBottlenecks removed, math on the board
Solidify5-10 minOps, edge cases, self-critique
Buffer~5 minInterviewer tangents — they aren’t free, protect them

If you finish early, don’t stop talking — pick a component and deepen it. The interview ends when the interviewer is satisfied, not when your diagram is.

How to Practice

System design is a performance skill; reading about it isn’t practicing it.

  • Rehearse out loud, timed. Two or three mocks a week at 40 minutes. Explain your reasoning while drawing — silence reads as uncertainty even when you know the answer.
  • Memorize the numbers. Latency of a memory read (~100 ns), SSD read (~100 µs), network round-trip (~500 µs intra-DC), disk seek (~10 ms), a request across the Atlantic (~150 ms). Those numbers turn “fast” and “slow” from opinions into arguments.
  • Study real architectures. Engineering blogs and postmortems (how Discord stores messages, how Stripe handles idempotency) give you production detail that generic guides don’t.
  • Do the same problem twice. Solve a problem once, read a canonical solution, solve it again a week later and note where your decisions diverged.
  • Record yourself. Filler words, missing signposts (“now I’ll handle the read path”), and sunk time are invisible until you hear them.

A Question Bank to Rehearse

These are the classics interviewers reach for. Work through them in roughly this order — each prompt trains a different muscle:

  • Design a rate limiter: token bucket state, distributed counters, consistency at the edge.
  • Design a web crawler: frontier queues, politeness, deduplication at billion-page scale.
  • Design a chat system: real-time delivery, ordering, presence — sketched above.
  • Design a news feed / Twitter: fan-out push vs. pull, the celebrity problem, ranking signals.
  • Design a distributed cache: sharding, eviction, replication — Redis internals in reverse.
  • Design a ride-sharing service: geospatial indexes, matching, surge logic, state machines.
  • Design a video platform: object storage, CDN strategy, upload pipelines, thumbnail processing.
  • Design file sync (Dropbox): chunking, deduplication, delta sync, conflict resolution.
  • Design a metrics pipeline: write-heavy ingestion, time-series storage, rollups.
  • Design a key-value store: consistency models, quorum reads and writes, gossip protocols — the “design Dynamo” classic.

Solve each one cold at 40 minutes, then re-solve the ones where you froze. A prompt you’ve rehearsed twice is rarely the one that fails you; an unpracticed category is.

What Works

  • Start simple, then add complexity only when the stated requirements justify it.
  • State assumptions explicitly — interviewers score your reasoning, not your conclusions.
  • Quantify claims: “read-heavy” means nothing until it becomes “100:1 read-to-write ratio.”
  • Know your own stack deeply; never propose a technology you can’t explain two levels down.
  • Treat interviewer hints as requirements, not as suggestions to consider later.
  • Practice with a timer. Forty-five minutes goes faster than you think.

Common Mistakes

  • Jumping into a detailed database schema before clarifying a single requirement.
  • Ignoring non-functional requirements — scale, availability, consistency — until the end.
  • Proposing technologies without understanding them (“use Kafka” without being able to say why a queue beats a direct call here).
  • Not discussing trade-offs, e.g., glossing over SQL vs. NoSQL as if the choice were free.
  • Forgetting monitoring, security, and operational concerns until reminded.
  • Designing for infinite scale when the stated requirements don’t justify it — it signals cargo-cult reasoning, not seniority.
  • Going silent while drawing. Narrate continuously or the interviewer can’t score your reasoning.

See Also

Frequently Asked Questions

How deep should I go into a specific technology?

Deep enough to explain why you chose it and what it costs. If you say Redis, be ready for eviction policies, persistence options, and what happens when it runs out of memory. If you can only name it, leave it out of the design.

Should I mention specific cloud providers?

Use generic terms — "object storage" instead of "S3" — unless the interviewer asks for specifics or you're interviewing at that provider. Generic vocabulary proves you think in architectural roles rather than vendor products.

What if I don't know a technology the interviewer asks about?

Say so plainly, then reason about it anyway: "I haven't used Cassandra, but I understand it's a wide-column store optimized for write-heavy workloads — which is why it fits click analytics." Honesty plus reasoning beats bluffing, which interviewers detect almost immediately.

How do I estimate storage and bandwidth in an interview?

Start from the numbers in the requirements. Daily writes and reads × record size = daily storage; × 365 = yearly. Add ~20% for indexes and metadata overhead. For bandwidth, multiply requests/second by average response size. State assumptions, round aggressively, and keep going — the interviewer cares about the process, not whether your answer is off by 10%.

What should I do if I get stuck partway through?

Verbalize the blocker instead of going quiet: "I'm not sure whether read replicas alone cover 300k reads/s — let me check the math." Interviewers interpret stuck-but-reasoning as recoverable; stuck-and-silent isn't. You can also just ask — a well-framed question under pressure counts for more than a memorized answer.

How much database schema detail should I give?

Name the tables, the partition or shard keys, and the two or three columns that drive the queries — then stop. Interviewers want to see that your schema serves the access patterns you described, not a full DDL dump. Offer to go deeper only if they ask.