System Design Interview Questions & Answers
The most common system design interview questions asked at Google, Amazon, Meta, and Microsoft — with detailed answers covering architecture, scaling strategies, and trade-offs.
How to Approach Any System Design Question
- 1
Clarify requirements
Functional and non-functional (scale, latency, consistency). Always ask about expected traffic, data volume, and read/write ratio.
- 2
Estimate scale
Daily active users, requests per second, storage needs, bandwidth. Use back-of-envelope math — interviewers expect rough estimates.
- 3
Design high-level architecture
Components and data flow: clients, load balancers, application servers, databases, caches, message queues.
- 4
Deep-dive into components
DB schema, caching strategy, sharding approach, API design. This is where most of the interview time is spent.
- 5
Discuss trade-offs
SQL vs NoSQL, push vs pull, consistency vs availability, sync vs async. Name at least 3 trade-offs.
- 6
Address failure modes
What happens when a service goes down? How do you handle data loss? Replication strategy? Monitoring and alerting?
Top System Design Interview Questions
Design a URL Shortener (like TinyURL)
Key components: A Key Generation Service (KGS) that pre-generates random 6-character Base62 keys. When a user submits a URL, the app server requests a key from KGS, stores the mapping in a NoSQL database (Cassandra/DynamoDB), and returns the short URL. For redirects: look up the short key in cache (LRU/Memcached) first, then database on miss, and return a 302 redirect. Scale: ~500M new URLs/month = ~200 writes/sec, ~20K reads/sec (100:1 read/write ratio). Shard by key hash across database nodes. Cache the 20% most popular URLs (~170GB). Handle link expiry with a background cleanup job.
Design a Rate Limiter
Purpose: Protect backend services from abuse by limiting request rates. Algorithms: (1) Token Bucket — tokens refill at a fixed rate; each request consumes a token. Simple and widely used. (2) Sliding Window Log — store timestamps of each request in a sorted set; count requests in the last window. Precise but memory-intensive. (3) Sliding Window Counter — hybrid: weighted count from current + previous window. Good balance of accuracy and efficiency. Implementation: Deploy as middleware or API gateway (e.g., Kong, Envoy). Store counters in Redis (atomic INCR + EXPIRE). Return HTTP 429 with Retry-After header when rate exceeded. Consider per-user, per-IP, and per-API limits.
Design a Distributed Cache (like Redis)
Purpose: Reduce database load by storing frequently accessed data in memory. Architecture: Client → Cache Cluster → Database. Cache eviction policies: LRU (most common), LFU, TTL-based. Consistency strategies: (1) Cache-aside: app checks cache first, loads from DB on miss. (2) Write-through: writes go to cache and DB simultaneously. (3) Write-behind: writes go to cache, async to DB. Cache stampede: When a key expires and many requests hit simultaneously, use distributed locks or probabilistic early expiration. Sharding: Consistent hashing to distribute keys across cache nodes. Replication: Primary-replica for read scaling.
Design a Chat System (like WhatsApp)
Core features: 1:1 messaging, group chats, online status, message delivery (sent/delivered/read). Architecture: Clients connect via WebSocket to a Chat Service (maintains persistent connections). Use a message broker (Kafka) for message routing between servers. Store messages in Cassandra (optimized for write-heavy workloads, partition by chat_id). Presence service: Redis with TTL for online status heartbeat. Push notifications: APNs (iOS) and FCM (Android) via a notification service. Group messaging: Fan-out on write (pre-compute member lists) for small groups, fan-out on read for large groups. Message ordering: Use timestamp + sequence number per chat. Delivery guarantees: At-least-once with idempotency keys.
Design a News Feed (like Twitter)
Two core operations: Publishing a post and reading the feed. Fan-out on write (push model): When user posts, immediately compute feeds for all followers and store in a feed cache. Fast reads but expensive for users with millions of followers. Fan-out on read (pull model): When user opens feed, fetch latest posts from all followed users and merge. Cheaper writes but slow reads for users following many people. Hybrid approach (what Twitter uses): Fan-out on write for regular users (<10K followers), fan-out on read for celebrity users (>10K followers). Storage: Posts in Cassandra (partition by user_id), feed in Redis (sorted set by timestamp). Timeline construction: Merge-K sorted lists from followed users' recent posts.
Design a Video Streaming Service (like YouTube)
Upload flow: Client uploads video chunks to a Upload Service → stored in S3 → processed by a Transcoding Pipeline (multiple resolutions: 240p, 480p, 720p, 1080p) → metadata stored in database. Playback flow: Client requests manifest file (HLS/DASH) → CDN serves video chunks. Key components: CDN (CloudFront/Akamai) for global content delivery, Transcoding service (FFmpeg workers), Metadata DB (video title, description, view count). Scale: 500 hours of video uploaded per minute. Store raw + transcoded videos in S3 (tiered: Standard for recent, Glacier for old). Recommendations: Collaborative filtering + content-based. Ads: Pre-roll, mid-roll via an Ad Service.
Design a Web Crawler
Components: URL Frontier (queue of URLs to crawl), DNS Resolver (cache DNS lookups), Fetcher (download pages), Content Parser (extract text + links), Deduplication (URL + content fingerprinting), Storage (raw HTML + parsed data). Politeness: Respect robots.txt, rate-limit per domain (max 1 request/second per domain). BFS crawling (breadth-first by depth) for prioritization. Distributed: Multiple crawler workers pulling from a shared URL frontier (partitioned by domain for politeness). URL deduplication: Bloom filter for space-efficient URL checking, or persistent URL set in database. Content deduplication: SimHash for near-duplicate detection. Priority scoring: PageRank, freshness, domain authority.
Design a Payment System
Core requirements: Process payments reliably, handle failures gracefully, maintain consistency (never double-charge). Architecture: Payment Service → Payment Processor (Stripe/PayPal) → Bank Network. Idempotency: Each transaction has a unique idempotency key; retrying with the same key returns the original result. Two-phase commit for multi-service transactions (e.g., order service + payment service). Saga pattern: Break long transactions into compensating steps (if payment fails, reverse the order). PCI DSS compliance: Never store raw card numbers; use tokenization via payment processor. Reconciliation: Batch job to compare internal records with processor records daily. Fraud detection: Real-time scoring based on transaction patterns, velocity checks, and device fingerprinting.
Design a Distributed Key-Value Store
Like DynamoDB or Cassandra. Data model: Key-value pairs with configurable consistency. Partitioning: Consistent hashing with virtual nodes to distribute data across servers. Replication: N replicas per key, configurable W (write quorum) and R (read quorum) for tunable consistency (W + R > N = strong consistency). Conflict resolution: Vector clocks for causal ordering, last-write-wins for simplicity. Gossip protocol for cluster membership and failure detection. Anti-entropy with Merkle trees for replica synchronization. Read/write path: Client → coordinator node → lookup responsible nodes via consistent hash ring → parallel read/write. Quorum: If W=2, R=2, N=3, need 2 nodes to agree for both reads and writes.
Design a Search Autocomplete System
Architecture: Trie data structure storing all query prefixes with frequency counts. When user types, traverse trie to the current prefix node, return top-K children by frequency. Real-time updates: Periodically rebuild trie from query logs (every few hours), or use a streaming approach with a separate frequency tracker. Storage: Trie in memory for O(prefix_length) lookup. For distributed: Shard trie by prefix range across servers. Ranking: Blend frequency, recency, and personalization (user search history). Rate limiting: Debounce client requests (300ms delay after last keystroke). Edge cases: Handle typos with fuzzy matching (edit distance ≤ 1), handle multi-language. Cold start: Seed with trending searches and popular queries.
Design a Notification System
Channels: Push (iOS/Android), SMS (Twilio), Email (SES), In-app. Architecture: Notification Service receives requests → validates and stores in database → routes to channel-specific workers (Push Worker, SMS Worker, Email Worker) via message queue (Kafka/SQS). Prioritization: Critical (password reset) → high (payment confirmation) → normal (marketing). Rate limiting: Per-user and per-channel limits to avoid spam. Delivery tracking: Store status (sent/delivered/read) per notification. User preferences: Allow users to control which notifications they receive per channel. Template engine: Separate content from logic with variable interpolation. Retry logic: Exponential backoff with dead-letter queue for permanently failed notifications.
How do you handle database sharding?
Sharding splits a large database into smaller partitions (shards) distributed across multiple servers. Strategies: (1) Hash-based: hash the shard key to determine the shard. Even distribution but resharding is expensive. (2) Range-based: shard by value ranges (e.g., user IDs 1-1M on shard 1). Simple but can cause hotspots. (3) Directory-based: a lookup service maps keys to shards. Flexible but adds a single point of failure. Shard key selection: Choose a key with high cardinality and even distribution (e.g., user_id, order_id). Avoid keys that create hotspots (e.g., timestamps). Resharding: Use consistent hashing to minimize data movement when adding/removing shards. Cross-shard queries: Avoid joins across shards; use denormalization or a separate aggregation layer.
What is the CAP theorem and why does it matter?
The CAP theorem states that a distributed data store can provide at most two of three guarantees: Consistency (every read gets the most recent write), Availability (every request gets a non-error response), Partition tolerance (the system works despite network failures). Since network partitions are unavoidable in distributed systems, you must choose between CP (consistent but may reject requests during partitions — e.g., HBase, MongoDB with strong consistency) and AP (available but may return stale data — e.g., Cassandra, DynamoDB default). Most modern systems are AP with tunable consistency (e.g., Cassandra: quorum reads/writes for consistency, single-node reads for availability). Understanding CAP helps you make informed trade-off decisions in system design interviews.
Design a URL Redirect Service with Analytics
Beyond basic TinyURL, add click analytics: Track IP, user-agent, referrer, timestamp per redirect. Architecture: Redirect service checks cache → DB for URL mapping → logs click event to Kafka → analytics pipeline (Spark/Flink) aggregates into ClickHouse/BigQuery for dashboard. Short URL format: 6-8 character Base62. Custom aliases: Allow user-specified slugs with uniqueness check. Link expiry: TTL on database records + background cleanup. Geographic routing: Serve redirects from edge (Cloudflare Workers) for low latency. Anti-abuse: Scan URLs against safe-browsing APIs before creating short links. Analytics dashboard: Real-time click counts, geographic distribution, referrer breakdown, device breakdown.
How do you design for high availability?
High availability (HA) means the system remains operational despite failures. Strategies: (1) Redundancy: Deploy multiple instances across availability zones. No single points of failure. (2) Load balancing: Distribute traffic across instances (L7 load balancer: NGINX, ALB). Health checks to remove unhealthy instances. (3) Replication: Database primary-replica with automatic failover. (4) Circuit breakers: Prevent cascading failures — if a downstream service is failing, stop calling it and return fallback responses. (5) Graceful degradation: Serve cached data when the primary data source is unavailable. (6) Chaos engineering: Regularly inject failures (Netflix's Chaos Monkey) to test resilience. (7) Monitoring: Alert on error rates, latency percentiles (p99), and resource utilization. SLA target: 99.99% uptime = ~52 minutes downtime per year.
Practice with Real Case Studies
Apply these concepts with our detailed system design case studies — each includes architecture diagrams, deep dives, and trade-off analysis.