{}The Interview
Handbook

Tracks / System Design

Fundamentals & the interview framework

senior 10 questions · 7 min read system-designscalabilitycapframework

Questions in this set 10
  1. 01How should you structure a 45-minute system design interview?
  2. 02What numbers should you have memorised?
  3. 03Explain CAP, and why is "CP vs AP" an oversimplification?
  4. 04What consistency models should you be able to name?
  5. 05SQL vs NoSQL — how do you actually decide?
  6. 06Explain sharding and the strategies.
  7. 07How do you handle unique id generation across shards?
  8. 08What is a load balancer doing, and what algorithms matter?
  9. 09How do you design for high availability?
  10. 10What does "design for 10x growth" mean in practice?
01

How should you structure a 45-minute system design interview?

Do not start drawing boxes. Use this budget, out loud, and let the interviewer redirect you:

  1. Requirements (5 min). Functional ("users post, follow, read a feed"), non-functional (scale, latency target, availability, consistency needs, read:write ratio), and explicitly out of scope. Ask before assuming.
  2. Scale estimates (5 min). DAU → QPS → storage → bandwidth. One or two numbers that drive a decision, not a spreadsheet.
  3. API and data model (5-10 min). The endpoints and the core tables/entities. This is where most candidates skip ahead and lose points.
  4. High-level design (10 min). Client → CDN/LB → services → cache → database → queue. Draw it, then walk one read and one write through it.
  5. Deep dive (10-15 min). The interviewer picks, or you offer: "the feed fan-out is the interesting part — shall I go deeper there?"
  6. Bottlenecks, failure modes, trade-offs (5 min). What breaks at 10x, what happens when each component dies, what you would monitor.

The meta-skill being assessed is communication under ambiguity. State assumptions, justify choices, and name the trade-off you accepted. "I'd use Postgres because the data is relational and 50k QPS with read replicas is comfortably within range; if writes exceeded that I'd shard by tenant" beats any amount of technology-name-dropping.

02

What numbers should you have memorised?

operation latency
L1 cache reference 1 ns
main memory reference 100 ns
SSD random read 100 µs
round trip within a datacenter 500 µs
disk seek (HDD) 10 ms
round trip US → Europe 150 ms

Plus: 1 day ≈ 86,400 s (call it 100k for mental math); 1M writes/day ≈ 12/s; a single well-tuned Postgres handles ~10-50k simple QPS; Redis does ~100k ops/s per core; a modern server has 64-256 GB of RAM (so "does the working set fit in memory?" is often the whole design); 1 KB × 1M rows/day ≈ 1 GB/day ≈ 365 GB/year.

Estimation example: 100M DAU, each reading a 20-post feed twice a day = 4B reads/day ≈ 46k QPS average, ~140k peak. That number alone tells you the feed must be cached, not computed per request.

03

Explain CAP, and why is "CP vs AP" an oversimplification?

CAP says that during a network partition you must choose between consistency (every read sees the latest write) and availability (every request gets a non-error response). Without a partition you have both.

Why the crude version is misleading:

  • Partitions are rare; the interesting trade-off most of the time is latency vs consistency — which is PACELC: if Partition then A or C, Else Latency or Consistency. Naming PACELC is a strong signal.
  • "Consistency" in CAP means linearizability, not the C in ACID.
  • Real systems are tunable, not categorical: DynamoDB and Cassandra let you choose per query (R + W > N gives quorum consistency); Postgres with synchronous replication trades write latency for durability.

Give examples: a bank ledger needs C (refuse the write rather than allow a double-spend); a shopping cart or a like counter chooses A (accept the write, reconcile later — Amazon's original Dynamo paper is exactly this).

04

What consistency models should you be able to name?

  • Strong / linearizable — reads always see the latest committed write. Expensive, needs consensus (Raft/Paxos).
  • Sequential / causal — operations that are causally related are seen in order by everyone; concurrent ones may differ. Enough for most social features (you never see a reply before its parent).
  • Read-your-writes — a user always sees their own updates. The practical minimum for UX; implemented by routing that user's reads to the primary (or a sticky replica) for a few seconds after a write.
  • Monotonic reads — you never see time go backwards. Broken by round-robin routing across replicas with different lag.
  • Eventual — replicas converge if writes stop. Fine for a follower count, unacceptable for a balance.

The senior move is to apply different models to different data in the same system: strong for payments, eventual for view counts.

05

SQL vs NoSQL — how do you actually decide?

Ask what shape the access patterns are, not what is fashionable.

  • Relational (Postgres/MySQL) — the default. Transactions, joins, constraints, ad-hoc queries, mature tooling. Scales further than people think: partitioning, replicas and one big machine cover most products. Choose it unless you have a reason not to.
  • Document (MongoDB, DynamoDB) — flexible schema, single-key access at very high scale, denormalised documents matching the read pattern. Costs: no joins, you design for one access pattern and pay to add another, transactions are limited.
  • Wide-column (Cassandra, ScyllaDB) — huge write throughput, linear scaling, no single point of failure, tunable consistency. For time-series, event logs, messaging. Costs: query patterns must be fixed at table-design time; no joins or ad-hoc queries.
  • Key-value (Redis, Memcached) — cache, sessions, rate limits, leaderboards.
  • Search (Elasticsearch, OpenSearch) — inverted index for text relevance and facets. Always a secondary store fed from your source of truth; never the system of record.
  • Time-series (Timescale, InfluxDB, ClickHouse) — column-oriented, compressed, fast aggregation over time ranges. For metrics and analytics.
  • Graph (Neo4j) — when traversals of arbitrary depth are the core query (fraud rings, social distance).

Polyglot persistence is normal: Postgres as the source of truth, Elasticsearch for search, Redis for cache, ClickHouse for analytics — all fed by change data capture.

06

Explain sharding and the strategies.

Sharding splits data across independent databases so each holds a subset.

  • Range (user_id 1-1M → shard 1) — simple, supports range scans, but hot-spots on sequential keys.
  • Hash (hash(user_id) % N) — even distribution, but resharding moves nearly everything.
  • Consistent hashing — keys map onto a ring with virtual nodes, so adding a shard moves only 1/N of the keys. This is how Cassandra and DynamoDB partition.
  • Directory / lookup — a service maps key → shard. Maximum flexibility (per-tenant placement, easy migration), but the directory is now critical infrastructure.
  • Geographic — data lives near the user; also the answer to data-residency requirements.

The hard parts to volunteer: cross-shard joins and transactions (avoid them — denormalise, or use a saga), hot shards (one celebrity user; mitigate by splitting that key further or caching it hard), resharding without downtime (dual-write and backfill), and globally unique ids (Snowflake ids, or UUIDv7 for time-ordered locality).

07

How do you handle unique id generation across shards?

  • UUIDv4 — trivial, no coordination; but random, so it destroys index locality and is 16 bytes.
  • UUIDv7 / ULID — timestamp-prefixed, so sortable and index-friendly. The modern default.
  • Snowflake — 64 bits: timestamp + machine id + sequence. Sortable, compact, ~4k ids/ms per node. Needs machine-id assignment and is sensitive to clock skew (hence NTP and a monotonic-clock guard).
  • Database sequences with ranges — each shard is handed a block of ids; simple, but coordination on block exhaustion.

Say why it matters: sortable ids let you paginate by id, shard by time, and keep B-tree inserts appending to the right-hand edge rather than scattering.

08

What is a load balancer doing, and what algorithms matter?

L4 (TCP) balancing is fast and protocol-agnostic; L7 (HTTP) can route by path/header/cookie, terminate TLS, retry, and do canary splits. Algorithms: round-robin (simple), least-connections (better with variable request cost), least-outstanding-requests / power-of-two-choices (excellent in practice, cheap), consistent hashing (for cache affinity), and weighted variants for heterogeneous instances.

Beyond distribution: health checks (passive and active), connection draining on deploy, outlier ejection, and avoiding retry amplification — a retry at every layer turns one failure into an exponential storm, which is why retry budgets and circuit breakers exist.

09

How do you design for high availability?

Redundancy at every layer with no shared single point of failure: multiple instances behind a balancer across ≥2 availability zones, a replicated database with automated failover, stateless application servers (state in the database/cache/object store), and health checks that actually test dependencies.

Then the operational half: graceful degradation (serve stale cache or a reduced feature set rather than an error page), timeouts and circuit breakers on every external call, backpressure and load shedding, and a tested disaster-recovery path — an untested backup is not a backup. Quantify: 99.9% = 43 min/month of downtime, 99.99% = 4.3 min. Each nine multiplies cost, so ask what the business actually needs.

10

What does "design for 10x growth" mean in practice?

Identify the component that saturates first and the change you would make, without building it now:

  • Stateless app tier → horizontal autoscaling. Cheap.
  • Database reads → replicas, then caching, then denormalised read models.
  • Database writes → batching, then partitioning, then sharding. Expensive; design the key now so it is possible later.
  • One synchronous path doing five things → move four of them to a queue.
  • One shared queue → split by priority.

The strong answer names what you would not do yet: "I would not shard today; I would make sure the schema has a tenant id on every table so I can."