DSA DAY ONE
DSA DAY ONE
PART I — FOUNDATIONS
Chapter 1: C++ Essentials for DSA
Chapter 2: C++ STL Deep Dive
Chapter 3: Complexity Analysis
PART II — LINEAR DATA STRUCTURES
Chapter 4: Arrays & Strings
Chapter 5: Two Pointers & Sliding Window
Chapter 6: Hashing
Chapter 7: Linked Lists
Chapter 8: Stacks
Chapter 9: Queues & Deques
PART III — TREES
Chapter 10: Binary Trees
Chapter 11: Binary Search Trees (BST)
Chapter 12: Heaps & Priority Queues
Chapter 13: Tries (Prefix Trees)
Chapter 14: Segment Tree & Fenwick Tree
PART IV — ALGORITHMS
Chapter 15: Sorting Algorithms
Chapter 16: Binary Search
Chapter 17: Recursion & Backtracking
Chapter 18: Graphs — Fundamentals & Traversals
Chapter 19: Graph Algorithms — Shortest Paths, MST & Union-Find
Chapter 20: Dynamic Programming
Chapter 21: Greedy Algorithms
Chapter 22: Divide & Conquer
PART V — COMPETITIVE & MATH
Chapter 23: Bit Manipulation
Chapter 24: Math & Number Theory
PART VI — PATTERNS
Chapter 25: Pattern Recognition Mastery
PART VII — SYSTEM DESIGN
Chapter 26: System Design for FAANG Interviews
What Interviewers Actually EvaluateThe FAANG System Design FrameworkScalability — Horizontal vs. VerticalCore Building BlocksDatabases — SQL, NoSQL, Indexing & ReplicationCAP Theorem, ACID & BASEMessage Queues & Event-Driven ArchitectureAPI Design — REST, GraphQL & gRPCCase StudiesCompany-Specific Expectations
PART VIII — INTERVIEW STRATEGY
Chapter 27: Cracking FAANG — Strategy & Communication
26

System Design for FAANG Interviews


Chapter 26 ·  Part 7: SYSTEM DESIGN ·  Est. 25 min read

Chapter Goal: Build a structured, confident approach to system design interviews. Unlike coding rounds, there is no single correct answer — the interviewer is evaluating how you think, communicate trade-offs, and handle ambiguity at scale. This chapter gives you a repeatable framework, the core building blocks every distributed system uses, and five complete case studies that cover the most commonly asked design problems at FAANG companies.


26.1 What Interviewers Actually Evaluate

There Is No "Right" Answer

System design interviews are open-ended. The interviewer evaluates your thought process, not a specific architecture. Two candidates can draw completely different diagrams and both get the job — if both demonstrate strong reasoning about trade-offs.

The Four Dimensions of Evaluation

1. COMMUNICATION & STRUCTURE
   Can you break a vague requirement into concrete components?
   Do you drive the conversation or wait to be led?
   Do you clarify before diving in?

2. TECHNICAL BREADTH
   Do you know the right tools? (databases, queues, caches, CDNs)
   Can you describe how they work internally at a high level?
   Do you know when NOT to use a technology?

3. TRADE-OFF AWARENESS
   Do you recognize that every choice has costs?
   Can you articulate why you chose SQL over NoSQL?
   Do you understand consistency vs. availability vs. latency?

4. SCALE THINKING
   Can you estimate load and capacity?
   Do you identify bottlenecks before they're pointed out?
   Can you evolve the design as requirements change?

Level Expectations

Level Focus Depth Expected
Junior (L3/E3) Functional correctness, basic components One-region design, basic DB choice
Mid (L4/E4) Scalability awareness, caching, trade-offs Multi-server, cache layer, sharding
Senior (L5/E5) End-to-end ownership, bottlenecks, reliability Multi-region, advanced consistency
Staff (L6/E6) Novel insights, cross-system impact, future-proofing Full distributed system mastery

Common Mistakes to Avoid

❌ Jumping to solutions without clarifying requirements
❌ Gold-plating a simple design (over-engineering from the start)
❌ Treating databases as a black box ("just put it in the DB")
❌ Ignoring failure scenarios (what if a service goes down?)
❌ Not driving the conversation — waiting for the interviewer to ask
❌ Ignoring the non-functional requirements (latency, consistency, availability)
❌ Designing only the happy path (no error handling, retries, timeouts)

26.2 The FAANG System Design Framework

Use this framework for every system design interview. It keeps you structured, ensures you cover all dimensions, and signals seniority.

RESHADED — 8-Step Framework

R — Requirements          (5 min)  Clarify what we're building
E — Estimate              (3 min)  Numbers: QPS, storage, bandwidth
S — Storage Schema        (5 min)  What data do we store? How?
H — High-Level Design     (10 min) Components, diagram, data flow
A — APIs                  (5 min)  Define the key interfaces
D — Deep Dive             (15 min) Pick 2-3 critical components to detail
E — Extensions            (5 min)  Edge cases, failure handling, evolution
D — Deficiencies          (3 min)  What doesn't scale? What would you change?

Step R — Requirements (Ask These Questions)

Functional (what the system DOES):
  • "What are the core features? What should I prioritize?"
  • "Should I focus on reads or writes?"
  • "Do we need real-time? Or is eventual consistency OK?"

Non-functional (how well it does it):
  • "What scale are we designing for? DAU? QPS?"
  • "What's the acceptable latency? (p99, p50)"
  • "What consistency level is required?"
  • "What's the availability target? (99.9%? 99.99?)"
  • "Any geographic requirements? Multi-region?"

Step E — Estimation (Do the Math Aloud)

REFERENCE NUMBERS TO MEMORIZE:
  1 million users × 10 requests/day = ~120 QPS
  1 billion users × 10 requests/day = ~120,000 QPS (120K QPS)

  1 byte   = 1 B
  1 KB     = 10³ B
  1 MB     = 10⁶ B (≈ a small image)
  1 GB     = 10⁹ B (≈ a movie)
  1 TB     = 10¹² B
  1 PB     = 10¹⁵ B (Facebook stores petabytes daily)

  Typical DB read:     ~1ms (SSD), ~10ms (HDD)
  Typical cache hit:   ~0.1ms (in-process), ~1ms (Redis)
  Network round trip:  ~1ms (same DC), ~50ms (cross-continent)

ESTIMATION TEMPLATE:
  "Let's say 100M DAU, 10 requests per user per day.
   That's 10^9 requests/day = 10^9 / 86,400 ≈ 12,000 QPS peak.
   At 1KB per record, 100M users × 500 bytes = 50GB of user data.
   Storage growth: if 1M new records/day × 1KB = 1GB/day = 365GB/year."

26.3 Scalability — Horizontal vs. Vertical

Vertical Scaling (Scale Up)

Add more power to one machine: more CPU, RAM, faster disk.

Pros:  Simple, no code changes, strong consistency (one machine)
Cons:  Hard limit (biggest machine available), single point of failure,
       expensive at the top end, downtime for upgrades

Use when: Early stage, stateful services that can't distribute easily

Horizontal Scaling (Scale Out)

Add more machines, distribute load across them.

Pros:  Near-infinite scale, fault tolerant (one machine fails → others serve),
       cost-effective (commodity hardware)
Cons:  Distributed system complexity, consistency harder,
       stateful services need special handling (session affinity or shared state)

Use when: High traffic, need fault tolerance, stateless services

Stateless vs. Stateful Services

STATELESS (easy to scale horizontally):
  Any server can handle any request.
  Session data stored externally (Redis, DB), not on server.
  → Application servers, API gateways

STATEFUL (harder to scale):
  Server holds user-specific state (WebSocket connection, in-memory game state).
  Must route same user to same server OR externalize state.
  → Use sticky sessions or store state in external store (Redis)

26.4 Core Building Blocks

Load Balancers

PURPOSE: Distribute traffic across multiple servers, provide single entry point.

LAYER 4 (Transport): Routes by IP/TCP — fast, simple
LAYER 7 (Application): Routes by HTTP headers, URL, cookies — flexible

ALGORITHMS:
  Round Robin:       Distribute equally in order
  Weighted RR:       More powerful servers get more requests
  Least Connections: Route to server with fewest active connections
  IP Hash:           Same client always goes to same server (sticky)
  Consistent Hash:   For distributed caches and databases

TOOLS: Nginx, HAProxy, AWS ALB, Google Cloud LB

Caching

PURPOSE: Store frequently accessed data closer to the user.
         Dramatically reduces database load and latency.

CACHE-ASIDE (Lazy Loading) — Most Common:
  1. Check cache first
  2. Cache miss → read from DB, write to cache
  3. Future reads → cache hit

READ-THROUGH:
  Cache sits in front of DB. Cache handles the DB read on miss.

WRITE-THROUGH:
  Write to cache and DB simultaneously. Strong consistency, slower writes.

WRITE-BACK (Write-Behind):
  Write to cache only, sync to DB asynchronously. Fast writes, risk of data loss.

EVICTION POLICIES:
  LRU (Least Recently Used) — most common
  LFU (Least Frequently Used) — better for popularity skew
  TTL (Time-To-Live) — expire after fixed duration

CACHE LAYERS:
  L1: In-process (Java HashMap, Python dict) — fastest, not shared
  L2: Distributed (Redis, Memcached) — shared across servers
  L3: CDN — geographic caching for static assets

PROBLEMS:
  Cache stampede: Many requests miss at same time → DB overwhelmed
  → Solution: Mutex/lock on cache miss, or probabilistic early expiration

  Cache penetration: Requests for non-existent keys bypass cache
  → Solution: Cache null results, Bloom filter

  Cache avalanche: Many keys expire at once
  → Solution: Randomize TTL, circuit breaker

Content Delivery Network (CDN)

PURPOSE: Serve static content (images, videos, JS/CSS) from edge servers
         close to the user, reducing latency and origin server load.

TYPES:
  Push CDN: Upload content to CDN proactively (good for predictable content)
  Pull CDN: CDN fetches from origin on first request (good for varied content)

USE WHEN: Serving media, static assets, geographically distributed users
TOOLS: Cloudflare, AWS CloudFront, Akamai, Fastly

Sharding (Database Horizontal Partitioning)

PURPOSE: Split one large database into smaller pieces (shards).
         Each shard holds a subset of the data.

STRATEGIES:
  Hash Sharding:      shard = hash(user_id) % num_shards
    → Even distribution, poor range queries
  Range Sharding:     shard by date range, alphabetical range
    → Good range queries, hotspot risk (all new data → last shard)
  Directory Sharding: Lookup table maps key → shard
    → Flexible, but lookup table is a bottleneck/SPOF

PROBLEMS:
  Hotspot:    One shard gets disproportionate traffic
  Resharding: Adding new shards requires moving data (use consistent hashing)
  Joins:      Cross-shard joins are expensive → denormalize

CONSISTENT HASHING: Maps both servers and keys to a ring.
  Adding/removing a server only moves ~k/n keys (k=keys, n=servers)
  → Virtual nodes improve load balance

26.5 Databases — SQL, NoSQL, Indexing & Replication

SQL vs. NoSQL Decision Guide

USE SQL WHEN:
  ✅ Data is highly relational (joins are common)
  ✅ Strong ACID guarantees required (financial transactions)
  ✅ Schema is well-defined and stable
  ✅ Complex queries with aggregations
  Examples: PostgreSQL, MySQL, SQLite

USE NoSQL WHEN:
  ✅ Massive scale with horizontal sharding needed
  ✅ Schema flexibility required (varied document structures)
  ✅ Specific access patterns that don't require joins
  ✅ Eventual consistency is acceptable
  Examples: MongoDB, Cassandra, DynamoDB, Redis

NoSQL TYPES:
  Key-Value:    Redis, DynamoDB  → Fast O(1) access by key
  Document:     MongoDB          → JSON documents, flexible schema
  Wide Column:  Cassandra        → Time-series, write-heavy, AP system
  Graph:        Neo4j            → Highly connected data, social graphs
  Search:       Elasticsearch   → Full-text search, faceting

Indexing

PURPOSE: Speed up reads at the cost of write performance and storage.

B-TREE INDEX (default): Good for range queries (BETWEEN, >, <), ORDER BY
HASH INDEX:             Only exact match (=), very fast, no range support
COMPOSITE INDEX:        Multiple columns — column order matters!
  (city, last_name) → efficient for "WHERE city=X AND last_name=Y"
  but NOT for "WHERE last_name=Y" alone (must use leftmost prefix)

COVERING INDEX: Index contains all columns needed by query → no table access

RULE OF THUMB:
  • Index on columns in WHERE, JOIN, ORDER BY clauses
  • Avoid over-indexing: each index slows writes and uses storage
  • Low cardinality columns (gender, boolean) are poor index candidates

Replication

SINGLE-LEADER (Master-Slave):
  One leader accepts writes; replicas sync asynchronously.
  → Reads can go to replicas (scale read traffic)
  → Leader failure requires failover (data loss risk if async)
  USE: MySQL with read replicas, PostgreSQL streaming replication

MULTI-LEADER:
  Multiple leaders accept writes; sync with each other.
  → Write conflicts possible → need conflict resolution strategy
  USE: Multi-region setups, offline-capable clients (CouchDB)

LEADERLESS (Quorum-based):
  All nodes accept writes. Quorum determines consistency.
  W + R > N ensures strong consistency (W=write quorum, R=read quorum, N=replicas)
  Typically N=3, W=2, R=2 → strong; or W=1, R=1 → eventual
  USE: Cassandra, DynamoDB, Amazon Dynamo

26.6 CAP Theorem, ACID & BASE

CAP Theorem

In a distributed system, you can guarantee AT MOST 2 of:

  C — Consistency:         All nodes see the same data at the same time
  A — Availability:        Every request gets a response (may be stale)
  P — Partition Tolerance: System continues despite network partition

REALITY: Network partitions WILL happen → you must choose C or A.

CP Systems (Consistency + Partition Tolerance):
  • Return an error instead of stale data during partition
  • Examples: HBase, MongoDB (single-leader), Zookeeper, Redis Cluster
  • USE: Financial transactions, user authentication, inventory

AP Systems (Availability + Partition Tolerance):
  • Return the best available data during partition (may be stale)
  • Examples: Cassandra, CouchDB, DynamoDB, DNS
  • USE: Social feeds, shopping carts, DNS resolution

ACID vs. BASE

ACID (traditional relational databases):
  Atomicity:    Transaction fully completes or fully rolls back
  Consistency:  DB always transitions between valid states
  Isolation:    Concurrent transactions don't interfere
  Durability:   Committed data survives crashes (written to disk)

BASE (distributed NoSQL systems):
  Basically Available: System is available most of the time
  Soft state:          State may change even without new input (sync propagating)
  Eventually consistent: All replicas will agree... eventually

INTERVIEW TIP: "Our system needs X. That implies I should use a CP/AP system
because [trade-off reason]." Showing you can map requirements to consistency
model is a senior signal.

26.7 Message Queues & Event-Driven Architecture

Why Message Queues?

1. DECOUPLING: Producer and consumer are independent — can scale separately
2. BUFFERING: Absorb traffic spikes (queue holds excess, consumer processes at its pace)
3. RELIABILITY: Consumer can retry failed processing without losing the message
4. ASYNC PROCESSING: Return response to user immediately, process in background

USE CASES:
  • Sending emails/notifications after order placed
  • Video encoding pipeline after upload
  • Log aggregation and analytics
  • Microservice communication

Key Concepts

PRODUCER: Publishes messages to queue/topic
CONSUMER: Reads and processes messages
BROKER:   The queue service itself (Kafka, RabbitMQ, SQS)
TOPIC:    Named channel for messages (Kafka/Pub-Sub)
QUEUE:    Point-to-point channel (one consumer per message)

DELIVERY SEMANTICS:
  At-most-once:   Messages may be lost but never duplicated (fire and forget)
  At-least-once:  Messages may be duplicated but never lost (retry on failure)
  Exactly-once:   Never lost, never duplicated (hard, expensive — avoid if possible)

KAFKA vs. RabbitMQ vs. SQS:
  Kafka:    High throughput, persistent, replay-able, event log
            → Stream processing, event sourcing, large scale
  RabbitMQ: Rich routing, priority queues, flexible
            → Task queues, microservice communication
  SQS:      Managed, simple, integrates with AWS ecosystem
            → AWS-native workloads, serverless

Event-Driven Architecture Patterns

EVENT SOURCING:
  Store all state changes as immutable events.
  Current state = replay all events.
  → Full audit log, time-travel debugging, event replay
  → Complex: requires careful schema versioning

CQRS (Command Query Responsibility Segregation):
  Separate read model (optimized for queries) from write model.
  Writes update events; reads maintain denormalized read models.
  → Great for complex domains with different read/write access patterns

26.8 API Design — REST, GraphQL & gRPC

REST (Representational State Transfer)

PRINCIPLES:
  Stateless:      No client state on server between requests
  Resource-based: URLs represent nouns (/users, /posts), not verbs
  HTTP verbs:     GET (read), POST (create), PUT (replace), PATCH (update), DELETE

GOOD REST DESIGN:
  GET    /users/{id}        → Get user by ID
  POST   /users             → Create new user
  PUT    /users/{id}        → Replace user
  PATCH  /users/{id}        → Partial update
  DELETE /users/{id}        → Delete user
  GET    /users/{id}/posts  → Get posts by user (nested resource)

HTTP STATUS CODES:
  200 OK, 201 Created, 204 No Content
  400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found
  409 Conflict, 429 Too Many Requests (rate limiting)
  500 Internal Server Error, 503 Service Unavailable

VERSIONING: /api/v1/users, /api/v2/users (breaking changes need new version)

PAGINATION:
  Offset: GET /posts?page=2&limit=20 (simple but slow for large offsets)
  Cursor: GET /posts?after=post_xyz&limit=20 (efficient, stable under writes)

GraphQL

USE WHEN:
  • Multiple client types (web, mobile) need different data shapes
  • Avoiding over-fetching (REST returns full object, client needs 2 fields)
  • Avoiding under-fetching (REST needs multiple requests, GraphQL gets all at once)

query {
  user(id: "123") {
    name
    posts(limit: 5) {
      title
      createdAt
    }
  }
}

TRADE-OFFS:
  Pro: Flexible, reduces round trips, self-documenting
  Con: Complex caching (each query is different), N+1 query problem,
       harder rate limiting, security (queries can be arbitrarily expensive)

gRPC

USE WHEN:
  • Service-to-service communication (microservices internal APIs)
  • High performance with binary protocol (Protocol Buffers)
  • Streaming (bidirectional, server-side, client-side)
  • Strong typing across multiple languages

TRADE-OFFS:
  Pro: 5-10x smaller payload, faster, strongly typed, streaming support
  Con: Not human-readable, harder to debug, browser support limited

Rate Limiting

PURPOSE: Prevent abuse, ensure fair usage, protect backend.

ALGORITHMS:
  Token Bucket:    Tokens added at fixed rate, request consumes token.
                   Allows bursts up to bucket capacity. Most popular.

  Leaky Bucket:    Requests enter queue, processed at fixed rate.
                   Smooth output, no bursts. Good for stable rate enforcement.

  Fixed Window:    Count requests per fixed time window (1 min).
                   Simple but edge case: 2x traffic at window boundary.

  Sliding Window:  Count requests in last N seconds (rolling).
                   Accurate, more memory per user.

IMPLEMENTATION: Redis with INCR + EXPIRE, or Redis sorted sets (timestamp-based)
WHERE TO ENFORCE: API Gateway, Nginx, application layer
RETURN: 429 Too Many Requests with Retry-After header

26.9 Case Studies

Case Study 1 — Design a URL Shortener (bit.ly)

Requirements:

  • Functional: shorten URL, redirect to original, (optional: analytics)
  • Non-functional: 100M URLs, 10:1 read:write ratio, low latency redirects, highly available

Estimation:

100M URLs stored. Average URL = 100 bytes.
Storage: 100M × 100B = 10GB (easily fits in one DB, but we'll shard)
Write QPS: 1,000/s; Read QPS: 10,000/s

Key Design Decision — Generating Short Codes:

Option A: MD5 hash of long URL → take first 7 chars → base62 (62^7 = 3.5 trillion unique)
  Problem: Hash collision → check DB, regenerate → slow path

Option B: Auto-increment ID → encode to base62
  ID=12345 → base62 → "dnh"  (deterministic, no collision)
  Problem: Predictable IDs → competitors can enumerate your URLs
  Solution: Randomize ID generation order (KGS: Key Generation Service)

Option C: Key Generation Service (KGS)
  Dedicated service pre-generates keys, marks as used/unused
  App servers request keys from KGS — very fast, no collision
  KGS can have multiple instances with disjoint key ranges

Architecture:

Client → CDN (cache popular redirects)
       → Load Balancer
       → App Servers (stateless, can scale horizontally)
       → Cache (Redis: shortCode → longURL, ~80% cache hit rate)
       → Database (MySQL for metadata, Cassandra for analytics clicks)

URL Table:
  short_code (PK, VARCHAR 7) | long_url (TEXT) | created_at | user_id | expires_at

Redirect flow:
  GET /abc123 → check cache → hit: 301/302 redirect
              → miss: DB lookup → cache → redirect
  301 (Permanent): Browser caches, no future requests → less traffic
  302 (Temporary): Browser always checks server → accurate analytics

Case Study 2 — Design Twitter / News Feed

Requirements:

  • Functional: tweet, follow users, see home timeline (tweets from people I follow)
  • Non-functional: timeline loads in < 200ms, handle celebrities (millions of followers)

The Core Challenge — Fan-out:

When user A (10M followers) tweets:
  Option 1: FAN-OUT ON WRITE (Push model)
    → On tweet: write to all 10M followers' feed caches immediately
    → Pro: Fast timeline read (pre-computed)
    → Con: Write amplification for celebrities (10M writes per tweet!)

  Option 2: FAN-OUT ON READ (Pull model)
    → On timeline load: fetch tweets from all K people I follow, merge, sort
    → Pro: No write amplification
    → Con: Slow timeline load for users who follow many people

  HYBRID SOLUTION (Twitter's actual approach):
    Regular users → Fan-out on write (push to feed cache immediately)
    Celebrities (> 1M followers) → Fan-out on read (fetch and merge at read time)
    Mix: Pre-compute feed for regular followees, merge with celebrities at read

Architecture:

WRITE PATH:
  Client → LB → Tweet Service → Message Queue (Kafka)
  Fan-out Worker (consumes from Kafka) →
    [Regular users]: Push to followers' feed cache (Redis Sorted Set by timestamp)
    [Celebrities]:   Store tweet in celebrity's own cache only

READ PATH (Timeline):
  Client → LB → Timeline Service →
    Fetch pre-computed feed from Redis (regular followees) +
    Fetch last 20 tweets from each celebrity I follow +
    Merge & sort by time → return top 20

Tweet Table (Cassandra):
  tweet_id (TimeUUID PK) | user_id | content | created_at | media_url

User Feed Cache (Redis Sorted Set):
  Key: "feed:user_id"
  Score: timestamp (sorted for timeline order)
  Value: tweet_id
  Max 800 tweets cached per user (old ones evicted)

Case Study 3 — Design a Rate Limiter

Requirements:

  • Functional: limit API calls per user per time window
  • Non-functional: low latency (< 5ms overhead), distributed (multiple API servers)

Algorithm Selection:

TOKEN BUCKET (Most Recommended for APIs):
  Each user has a bucket with capacity C (burst limit).
  Tokens added at rate R per second.
  Request consumes 1 token. If empty → reject (429).
  Allows controlled bursts. Widely used (AWS, Stripe).

REDIS IMPLEMENTATION (Token Bucket with Lua script):
  Lua script is atomic — no race conditions across distributed servers

  -- Lua script for token bucket
  local tokens_key = KEYS[1]
  local last_refill_key = KEYS[2]
  local capacity = tonumber(ARGV[1])
  local refill_rate = tonumber(ARGV[2])
  local now = tonumber(ARGV[3])

  local last_refill = tonumber(redis.call('get', last_refill_key)) or now
  local tokens = tonumber(redis.call('get', tokens_key)) or capacity

  -- Refill tokens based on elapsed time
  local elapsed = now - last_refill
  tokens = math.min(capacity, tokens + elapsed * refill_rate)

  if tokens >= 1 then
      redis.call('set', tokens_key, tokens - 1, 'EX', 3600)
      redis.call('set', last_refill_key, now, 'EX', 3600)
      return 1  -- Allowed
  else
      return 0  -- Rejected (429)
  end

SLIDING WINDOW LOG (Most Accurate, More Memory):
  Redis Sorted Set per user: {timestamp → timestamp}
  On request:
    1. Remove entries older than window_start
    2. Count remaining entries
    3. If count < limit: add current timestamp, allow
    4. Else: reject

DISTRIBUTED CONSIDERATIONS:
  • Use Redis as centralized rate limit store (not per-server)
  • Redis cluster for high availability
  • Sticky sessions optional but not required (Redis is shared state)
  • Fallback: if Redis is down, fail open (allow traffic) or fail closed

Architecture:

Client → API Gateway (applies rate limit check) → Backend Services
  API Gateway: Read/Write to Redis rate limit store
  Redis: Stores per-user token counts / request logs
  Response Headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset

Case Study 4 — Design a Key-Value Store

Requirements:

  • Functional: get(key), put(key, value), delete(key)
  • Non-functional: highly available, durable, horizontally scalable, low latency

Core Decisions:

1. DATA PARTITIONING: Consistent Hashing
   • Place both servers and keys on a hash ring
   • Key maps to first server clockwise on ring
   • Virtual nodes (150-200 per server) ensure even distribution
   • Adding a server: only the next server's keys move

2. REPLICATION: Replicate to N=3 nodes clockwise on ring
   • Quorum: W + R > N for strong consistency
   • W=2, R=2, N=3 → tolerate 1 replica failure with strong consistency
   • W=1, R=1 → eventual consistency, highest availability

3. CONFLICT RESOLUTION: Vector Clocks
   • Each write has a vector clock [server: version]
   • Detect concurrent writes → surface conflict to client
   • Last-Write-Wins simpler but loses data

4. FAILURE DETECTION: Gossip Protocol
   • Each node periodically sends heartbeat to random nodes
   • If node hasn't been heard from → mark suspicious
   • Propagates failure information without central coordinator

5. STORAGE ENGINE: LSM Tree (Log-Structured Merge-Tree)
   • Writes go to in-memory MemTable (sorted)
   • Flushed to SSTable on disk when full
   • Compaction merges SSTables periodically
   • Fast writes, acceptable reads (check MemTable, then SSTables)
   • Used by: RocksDB, Cassandra, LevelDB

Architecture:

Client → Coordinator Node (handles routing, consistent hashing)
       → Replica Nodes (3 copies of data)

Each Node Contains:
  MemTable (in-memory sorted buffer) →
  Write-Ahead Log (WAL, for durability) →
  SSTables (immutable sorted files on disk)

Read Path:
  Check MemTable → Check Bloom filters → Check SSTables (newest first)

Write Path:
  1. Write to WAL (durable)
  2. Write to MemTable (fast, in-memory)
  3. When MemTable full → flush to SSTable
  4. Periodic compaction (merge + garbage collect)

Case Study 5 — Design Netflix / Video Streaming

Requirements:

  • Functional: upload video, browse catalog, stream video, recommendations
  • Non-functional: global low latency streaming, handle 200M users, high availability

Key Insight: Video Storage Is Not Databases

Video files are HUGE (a 2-hour movie = 4-8GB in 4K).
Cannot store in traditional databases.
Solution: Object storage (AWS S3, Google Cloud Storage) + CDN

Video Upload & Processing Pipeline:

[Creator uploads video]
     ↓
Raw Video Storage (S3)
     ↓
Message Queue (SQS/Kafka) → triggers encoding workers
     ↓
Transcoding Workers (FFmpeg): Convert to multiple formats & resolutions:
  4K HEVC, 1080p H.264, 720p, 480p, 360p, 144p
  HLS (HTTP Live Streaming) — segments into 10-second chunks
  DASH (Dynamic Adaptive Streaming over HTTP) — same concept
     ↓
Encoded segments pushed to CDN edge servers globally
     ↓
Metadata stored in DB (title, description, duration, segment manifests)

Video Streaming (Adaptive Bitrate):

1. Client requests manifest file (.m3u8 for HLS)
   → Lists all available quality levels and segment URLs

2. Client selects quality based on current bandwidth:
   - Bandwidth high → request 1080p segments
   - Bandwidth drops → switch to 480p (adaptive bitrate)

3. Segments fetched from nearest CDN edge server:
   - Edge server has content cached
   - Cache miss → fetch from origin (S3), cache locally
   - No single server handles full video stream

4. Client buffers 2-3 segments ahead for smooth playback

KEY METRIC: Buffer stall rate (rebuffering) — Netflix targets < 0.1%

Recommendation System (High Level):

Offline (Batch):
  • Collaborative filtering: "Users like you also watched X"
  • Content-based: Match genre/director/actor to your history
  • Matrix factorization (SVD) on user-item rating matrix
  • Runs nightly on Spark/Flink

Online (Real-time):
  • Adjust ranking based on current session behavior
  • "Trending now" computed with sliding window

A/B Testing: Different algorithms tested on user segments

Architecture:

Client → CDN (video segments, thumbnails, static assets)
Client → API Gateway → Microservices:
  - Catalog Service (PostgreSQL + Elasticsearch for search)
  - User Service (MySQL)
  - Recommendation Service (custom ML models)
  - Playback Service (returns CDN manifest URLs)
  - Billing Service (Stripe integration)

Data Pipeline:
  User events (play, pause, seek, skip) → Kafka → Flink/Spark
  → Analytics DB (ClickHouse/Redshift) → Dashboard
  → Feature store → Recommendation model retraining

26.10 Company-Specific Expectations

Google

Emphasis: Clean abstraction, handling massive scale, distributed systems depth
Typical questions: Google Maps, YouTube, Google Docs (real-time collaboration)
Tips:
  • Think about data at petabyte scale
  • Discuss data structures and algorithms for core components
  • Google values Bigtable/Spanner/MapReduce-like approaches
  • Show understanding of consistency models

Meta (Facebook)

Emphasis: Real-time features, graph data, fast iteration
Typical questions: News Feed, Instagram, WhatsApp, Messenger
Tips:
  • Fan-out is always a key problem (social graphs)
  • Privacy at scale (data access controls)
  • Graph databases or adjacency lists for social connections
  • Discuss multi-region replication

Amazon

Emphasis: Leadership Principles, AWS services, fault tolerance
Typical questions: Amazon checkout, inventory system, delivery tracking
Tips:
  • Name AWS services explicitly (SQS, DynamoDB, ElastiCache, EC2)
  • Discuss failure modes extensively (what if this service dies?)
  • Idempotency is critical (retries must not double-charge)
  • Start with the customer experience, work backward (PRFAQ model)

Apple

Emphasis: Privacy-first design, global scale, device ecosystem
Typical questions: iCloud sync, Apple Pay, Siri
Tips:
  • End-to-end encryption discussion expected
  • On-device processing vs. cloud (privacy trade-off)
  • Cross-device sync with conflict resolution
  • Battery impact of mobile clients

Netflix

Emphasis: Microservices, chaos engineering, resilience
Typical questions: Recommendation system, video streaming pipeline, billing
Tips:
  • Discuss circuit breakers (Hystrix pattern)
  • Canary deployments and feature flags
  • Chaos Monkey: design for failure, not against it
  • Mention Netflix OSS: Eureka (service discovery), Ribbon (load balancing)

← PreviousChapter 25: Pattern Recognition MasteryNext →Chapter 27: Cracking FAANG — Strategy & Communication
Chapter 26 — Progress
0 / 28 COMPLETE
Framework & Process
  • Know RESHADED: Requirements, Estimate, Storage, High-level, APIs, Deep dive, Extensions, Deficiencies
  • Always clarify functional vs. non-functional requirements before designing
  • Do a back-of-envelope estimation (QPS, storage, bandwidth) before drawing diagrams
  • Drive the conversation — don't wait for the interviewer to lead you
Scalability
  • Know vertical vs. horizontal scaling trade-offs
  • Know why stateless services scale better horizontally
  • Know consistent hashing and when it beats simple hash-mod
Building Blocks
  • Know load balancer algorithms: round-robin, least-connections, consistent hash
  • Know 4 cache write policies: cache-aside, read-through, write-through, write-back
  • Know LRU, LFU, TTL eviction strategies
  • Know sharding strategies and their trade-offs: hash, range, directory
  • Know CDN push vs. pull models
Databases
  • Know when to use SQL vs. each NoSQL type (KV, document, wide-column, graph)
  • Know B-tree vs. hash indexes and when to use each
  • Know single-leader, multi-leader, and leaderless replication
  • Know read replicas for scaling reads
Distributed Systems Theory
  • State CAP theorem: C/A/P, can only guarantee 2 — but P is mandatory, so it's C vs A
  • Know 5 CP and AP systems as examples
  • Distinguish ACID vs BASE
  • Know quorum: W + R > N for strong consistency
Message Queues
  • Know token bucket, leaky bucket, fixed window, sliding window rate limiting
  • Know at-most-once, at-least-once, exactly-once delivery semantics
  • Know when to use Kafka vs. RabbitMQ vs. SQS
Case Studies (Know All Five)
  • URL Shortener: KGS, base62, cache-aside, 301 vs 302
  • Twitter Feed: fan-out on write vs. read, hybrid for celebrities
  • Rate Limiter: token bucket in Redis with Lua, X-RateLimit headers
  • Key-Value Store: consistent hashing, quorum, vector clocks, LSM tree
  • Video Streaming: transcoding pipeline, adaptive bitrate (HLS/DASH), CDN
Notes▸