RSRobince Studio

System Design interview revision notes

System design for interviews and real systems. Written for developers preparing for an interview who want to refresh their System Design fast. Free, no sign-up.

10 topics in these notes

  1. What is system design? (Goals: scale, availability, latency)
  2. Back-of-the-envelope estimation (QPS, storage, bandwidth)
  3. Load balancing & horizontal scaling
  4. Caching (strategies, CDN, Redis)
  5. Databases: SQL vs NoSQL, sharding & replication
  6. Message queues (async, decoupling, rate leveling)
  7. CAP theorem & consistency models
  8. Rate limiting & idempotency
  9. Example: Design a URL shortener
  10. System design interview checklist

What is system design? (Goals: scale, availability, latency)

Simple real-life example (Understand first — very important for understanding)

  • Like designing a highway: you think about how many cars (throughput), how fast they get through (latency), and what happens when a lane is closed (availability).
  • System design is turning vague requirements ("build X") into a concrete, scalable, and reliable design.

Real-world idea: you clarify functional and non-functional requirements, estimate load and storage, then choose components (APIs, DBs, caches, queues) and how they connect so the system can scale and stay available.

Technical definition

  • Functional requirements: what the system does (e.g. shorten URL, post tweet, process payment).
  • Non-functional: scale (QPS, users, data size), latency (p99), availability (99.9%), consistency (strong vs eventual).
  • Output: high-level components, data flow, key algorithms, and trade-offs (e.g. consistency vs availability).

Why it matters

System design interviews test how you handle ambiguity, estimate, and make trade-offs. Start by clarifying requirements and constraints.

Interview tip

Say: "I start by clarifying functional and non-functional requirements—scale, latency, availability. Then I estimate (QPS, storage), sketch components, and discuss trade-offs."

Back-of-the-envelope estimation (QPS, storage, bandwidth)

Simple real-life example (Understand first — very important for understanding)

  • Rough numbers to see if the design is in the right ballpark: how many requests per second? How much data in a year? How much network traffic?
  • Use round numbers (e.g. 1M DAU, 10 requests/user/day) and simple math to get order-of-magnitude answers.

Real-world idea: estimation helps you choose the right components (single server vs distributed, SQL vs NoSQL, need for cache). It’s not about exact numbers but about reasoning.

Technical definition

  • QPS: requests per second. E.g. 1M DAU × 10 req/day → ~10M req/day → ~100–200 QPS (with peak factor).
  • Storage: e.g. 1M users × 1 KB profile × 5 years growth → order of TB.
  • Bandwidth: QPS × response size; e.g. 1K QPS × 10 KB = 10 MB/s. Assume 2–3× for peak.

Code example

DAU = 1M, req/user/day = 10
Daily requests = 10M
QPS ≈ 10M / 86400 ≈ 120 (avg); peak ~3–5× → 400–600 QPS

Storage: 1M users × 10 KB = 10 GB (today); 5 yr × growth → plan for 100s GB–TB

Why it matters

Interviewers expect you to estimate. It shows you think about scale and drives the rest of the design.

Interview tip

Practice: DAU → daily requests → QPS (with peak factor); users × data size × retention → storage. State assumptions (e.g. 10 req/user/day) and round to powers of 10.

Load balancing & horizontal scaling

Simple real-life example (Understand first — very important for understanding)

  • Like multiple checkout counters: a single entry (load balancer) sends each customer to an free counter (server). If one counter goes down, others take the load.
  • Horizontal scaling = add more counters instead of making one counter super fast.

Real-world idea: a load balancer distributes requests across many app servers so you can handle more traffic and tolerate failures. App servers should be stateless so any server can serve any request.

Technical definition

  • Load balancer (LB): L4 (TCP) or L7 (HTTP); algorithms: round-robin, least connections, weighted, IP hash.
  • Health checks: LB stops sending traffic to unhealthy instances.
  • Stateless app: no local session; use sticky session only if needed; store session in Redis/DB.
  • Auto-scaling: add/remove instances based on CPU, request count, or queue depth.

Why it matters

Load balancing and horizontal scaling are baseline for any scalable system. You must be able to draw and explain them.

Interview tip

Say: "Traffic hits a load balancer that spreads requests across app servers. Servers are stateless; we scale by adding instances. We use health checks so failed instances are removed from the pool."

Caching (strategies, CDN, Redis)

Simple real-life example (Understand first — very important for understanding)

  • Like a small desk drawer for things you use often—you don’t go to the filing cabinet (DB) every time. Cache = fast copy of data closer to the user or app.
  • CDN: copies of static (or dynamic) content near users so pages and media load faster.

Real-world idea: cache reduces latency and load on the database. Choose what to cache (hot data), where (in-memory, Redis, CDN), and how to invalidate (TTL, event-based).

Technical definition

  • Cache-aside: app checks cache; on miss, load from DB and fill cache. Common; app controls invalidation.
  • Write-through: write to cache and DB together; read from cache. Good when writes are less frequent.
  • CDN: edge caches for static assets (and sometimes API responses); reduce latency and origin load.
  • Redis/Memcached: in-memory key-value; use for sessions, API responses, leaderboards. Set TTL and invalidation strategy.

Why it matters

Caching is one of the first levers in system design. Interviewers ask where you’d cache and how you’d invalidate.

Interview tip

Say: "We use cache-aside for hot read data in Redis; set TTL and invalidate on write. For static assets we use a CDN. I’d cache what’s read-heavy and can tolerate staleness."

Databases: SQL vs NoSQL, sharding & replication

Simple real-life example (Understand first — very important for understanding)

  • SQL: like a strict filing system with tables and relations; strong consistency and transactions.
  • NoSQL: like different filing styles—document (folder per entity), key-value (drawer per key), wide-column—often for scale and flexibility, with different consistency models.
  • Sharding: split data across many DBs (e.g. by user id) so no single DB holds everything. Replication: copy data to replicas for read scale and failover.

Real-world idea: choose SQL when you need ACID and complex queries; choose NoSQL when you need horizontal scale, flexible schema, or very high write throughput. Use sharding when one DB isn’t enough; use replication for reads and HA.

Technical definition

  • SQL: relational, ACID, schema, JOINs; vertical scale or read replicas; good for transactional and reporting workloads.
  • NoSQL: document (MongoDB), key-value (Redis), wide-column (Cassandra); often tune for scale and availability; eventual consistency common.
  • Sharding: partition data (e.g. by user_id % N); each shard is a DB; need strategy for cross-shard queries.
  • Replication: primary-replica; reads from replicas; failover to promote replica. Async replication → eventual consistency on read.

Why it matters

DB choice and scaling (replication, sharding) are central in system design. You must be able to justify SQL vs NoSQL and when to shard.

Interview tip

Say: "I use SQL for strong consistency and transactions; NoSQL when I need horizontal scale or flexible schema. I scale reads with replicas and scale writes with sharding when a single DB is the bottleneck."

Message queues (async, decoupling, rate leveling)

Simple real-life example (Understand first — very important for understanding)

  • Like a mail room: senders drop messages; receivers process when ready. Sender doesn’t wait; if there’s a burst, the queue absorbs it.
  • Decoupling: order service doesn’t need to know about inventory or email; it just publishes "order placed."

Real-world idea: queues decouple producers and consumers, allow async processing, and smooth out spikes. Use for background jobs, event propagation, and rate leveling.

Technical definition

  • Queue: FIFO or priority; at-least-once or exactly-once delivery; retention and dead-letter for failures.
  • Use cases: async tasks (email, notifications), decoupling services, buffering (producer faster than consumer), load leveling.
  • Examples: RabbitMQ (queues, routing), Kafka (log, replay, high throughput), SQS (managed, at-least-once).

Why it matters

Message queues are a standard ingredient in scalable and resilient designs. Interviewers ask when to use them and how they help.

Interview tip

Say: "We use a queue when we don’t need an immediate response—e.g. sending email after signup, or decoupling order and inventory. It gives async processing, decoupling, and smooths traffic spikes."

CAP theorem & consistency models

Simple real-life example (Understand first — very important for understanding)

  • CAP: in a partition (network split), you can’t have all three at once: Consistency (everyone sees same data), Availability (every request gets a response), Partition tolerance (system works despite network failures). In practice you choose between C and A when P happens.
  • Strong consistency: after a write, everyone sees it. Eventual: after a while, everyone sees the same data if no new writes.

Real-world idea: distributed systems face partitions; you trade off consistency vs availability. Many systems choose eventual consistency and use patterns (e.g. CRDTs, version vectors) to manage conflicts.

Technical definition

  • CAP: P is assumed (networks partition); so CP (consistency: block or error when split) vs AP (availability: respond with possibly stale data).
  • Strong consistency: linearizability; after write completes, all reads see it. Eventual: if writes stop, all replicas converge.
  • Practical: use strong consistency where needed (e.g. payment); eventual elsewhere with clear semantics and conflict handling.

Why it matters

CAP and consistency models are classic interview topics. You should be able to explain the trade-off and when to use which consistency.

Interview tip

Say: "Under partition we trade off C vs A. We use strong consistency for critical data (e.g. balance) and eventual consistency elsewhere, with idempotency and conflict resolution where needed."

Rate limiting & idempotency

Simple real-life example (Understand first — very important for understanding)

  • Rate limiting: like a bouncer—only N people per minute; protects the system from overload and abuse.
  • Idempotency: doing the same action twice (e.g. "charge $10") has the same effect as once. Critical when the client might retry; use idempotency keys so the server can detect duplicates.

Real-world idea: rate limiting protects APIs and backends; idempotency protects against duplicate charges or duplicate orders when clients or networks retry.

Technical definition

  • Rate limiting: limit requests per key (IP, user, API key). Algorithms: fixed window, sliding window, token bucket. Return 429 when exceeded; use headers (X-RateLimit-Remaining).
  • Idempotency: client sends Idempotency-Key (e.g. UUID); server stores key + result; same key returns same result without re-executing. Essential for POST/payment/order APIs.

Code example

// Rate limit: 100 req/min per user
if (await redis.incr(`ratelimit:${userId}`) === 1)
  await redis.expire(`ratelimit:${userId}`, 60);
if (await redis.get(`ratelimit:${userId}`) > 100) return res.status(429).send();

// Idempotency: key in header
const key = req.headers['idempotency-key'];
const cached = await redis.get(`idem:${key}`);
if (cached) return res.json(JSON.parse(cached));

Why it matters

Rate limiting and idempotency are expected in production API design. Interviewers often ask how you’d prevent abuse and duplicate operations.

Interview tip

Say: "We rate limit per user or API key (e.g. token bucket) and return 429 with Retry-After. For mutations we require an idempotency key and cache the result so retries are safe."

Example: Design a URL shortener

Simple real-life example (Understand first — very important for understanding)

  • User gives long URL → system returns short code (e.g. abc12). When someone visits short URL, we redirect to the long one. Need: generate short codes, store mapping, redirect fast, optional analytics.
  • Scale: billions of URLs; redirect is read-heavy; short code must be unique and compact.

Real-world idea: this is a classic system design exercise. It ties together: API design, storage (key-value or DB), short code generation (hash or base62 counter), cache for redirects, and optional analytics.

Technical definition

  • API: POST /shorten { longUrl } → { shortUrl }; GET /:code → 302 redirect to longUrl.
  • Short code: base62 encode auto-increment ID, or hash(longUrl) + collision handling. 6–7 chars → 62^6 ≈ 56B combinations.
  • Storage: shortCode → longUrl; key-value (Redis/DB). Cache shortCode → longUrl for redirect (high read).
  • Scale: stateless app servers, LB, cache layer, DB (shard by shortCode or use distributed ID).

Why it matters

URL shortener is a common interview problem. It exercises requirements, estimation, storage, cache, and scaling in one design.

Interview tip

Walk through: requirements (shorten, redirect, scale), estimate (QPS, storage), then components—API, short code generation (base62 ID), DB + cache for mapping, redirect flow. Mention duplicate longUrl (same or different short code) and TTL if needed.

System design interview checklist

Simple real-life example (Understand first — very important for understanding)

  • Clarify: what are we building? Who uses it? How big? Then estimate, draw boxes (components), then drill into data model, critical paths, and failure modes.
  • Always state assumptions and trade-offs; it’s okay to start simple and add scale step by step.

Real-world idea: use a repeatable flow: requirements → estimation → high-level design → data model and APIs → deep dive (e.g. DB, cache, queue) → scaling and failure handling.

Technical definition

  • Requirements: functional (features), non-functional (QPS, latency, availability, consistency).
  • Estimate: QPS, storage, bandwidth (back-of-envelope).
  • High-level: client, LB, app servers, cache, DB, queue. Draw and name components.
  • Data model: tables or key structure; indexes; sharding key if needed.
  • APIs: main endpoints, request/response; idempotency and rate limiting where relevant.
  • Deep dive: pick 2–3 areas (e.g. DB choice, caching, consistency) and explain in detail.
  • Failure: single points of failure; replication, failover; degradation (e.g. cache-only reads when DB is slow).

Why it matters

Having a checklist keeps you structured and ensures you don’t skip requirements or trade-offs.

Interview tip

Say: "I clarify scope and constraints, estimate load and storage, draw a high-level diagram with LB, app, cache, DB, queue. Then I detail data model and APIs, pick one or two areas to go deep, and discuss failure and scaling."

More Design & Architecture notes

OOP · Data Structures · Microservices · Project Architecture · All developer notes