Skip to main content
System design interview guide · Updated November 6, 2026

System design interview questions: 18 classics, answered step by step

System design interview questions ask you to design a large system, such as a URL shortener, a chat app or a payment ledger, in 45 to 60 minutes on a whiteboard. The 18 below are the ones that come up most. Each has what the interviewer is testing, the requirements to clarify, the numbers to estimate, a core design with a diagram, the deep dives to offer and the mistakes to avoid. Answer every one with the same six steps: requirements, estimates, API and data, high-level design, deep dives and wrap up.

classic questions, each with a diagram
18
steps to answer any of them
6
in a typical system design round
45-60 min
to prepare well
2-4 weeks
Table of contents

The 18 system design interview questions at a glance

In the order of the OphyAI practice library, from the starter question to the advanced ones. Each name jumps to its full answer.

#QuestionCore ideaLevelMock round
1URL shortenerUnique short codes and a read path built for cachingStarter35 min
2Rate limiter for a public APIToken buckets, atomic counters and limits across regionsCore45 min
3News feedFan-out on write vs read, and accounts with millions of followersCore45 min
4Chat appPersistent connections, ordering, delivery receipts and presenceCore45 min
5Ride-hailing dispatchA geo index under heavy writes, and matching without double bookingAdvanced60 min
6Payment ledgerIdempotency, a double-entry ledger and reconciliationAdvanced60 min
7Video upload and streamingChunked uploads, a transcoding pipeline and CDN deliveryAdvanced60 min
8Web crawlerThe URL frontier, politeness per host, and dedupeCore45 min
9Notification systemQueues per channel and priority, retries and user preferencesCore45 min
10Search autocompleteA prefix index with precomputed top results, at very low latencyCore45 min
11File storage and syncChunking, dedupe, delta sync and conflictsAdvanced60 min
12Ticket booking with seat holdsSeat holds that expire, and surviving on-sale spikesCore45 min
13Real-time leaderboardSorted sets, rank queries and shardingCore45 min
14Hotel reservationsInventory per night, the last room, and safe retriesCore45 min
15Food delivery trackingAn order state machine, dispatch timing and a live ETAAdvanced60 min
16Distributed cacheConsistent hashing, hot keys and staying in step with the databaseAdvanced60 min
17Metrics and alertingTime-series ingest, downsampling and alerting that keeps workingAdvanced60 min
18Ad click aggregatorStream windows, exactly-once counts and late eventsAdvanced60 min
The method

How to answer any system design question

Use the same six steps every time. The minutes are targets for a 45 or a 60 minute round. They are a guide, not a rule.

45 min
  1. Step 1: Requirements5m
  2. Step 2: Estimates4m
  3. Step 3: API and data6m
  4. Step 4: High-level design12m
  5. Step 5: Deep dives14m
  6. Step 6: Wrap up4m
60 min
  1. Step 1: Requirements7m
  2. Step 2: Estimates5m
  3. Step 3: API and data8m
  4. Step 4: High-level design16m
  5. Step 5: Deep dives19m
  6. Step 6: Wrap up5m
Time targets for a 45 and a 60 minute round. Deep dives get the most time; offer one by about two thirds of the way in.
  1. 01 · 5 min of 45 · 7 min of 60

    Requirements

    Ask who uses it, the 3 to 5 features that matter most, the scale, and the goals for latency, availability and consistency. Write them on the board and say what is out of scope.

    "So: create and redirect, 100M new links a day, redirects under 50 ms, and analytics can lag a few minutes. Custom domains are out of scope. Does that match what you had in mind?"

  2. 02 · 4 min of 45 · 5 min of 60

    Estimates

    Size reads and writes per second, storage and bandwidth, on average and at peak. Round hard. Then say what the numbers mean for the design.

    "120k reads a second is 100 times the writes, so the read path gets a cache, and 90 TB over 5 years means the store has to be sharded."

    How to estimate QPS, storage and bandwidth
  3. 03 · 6 min of 45 · 8 min of 60

    API and data

    Write the main endpoints with their key parameters, and the core tables or key-value schemas with their keys. Pick the store from how the data is read.

    "Every redirect is a lookup by code, so a key-value store keyed by code fits better than joins in a relational database."

  4. 04 · 12 min of 45 · 16 min of 60

    High-level design

    Draw the main boxes and arrows for each core flow and walk one request from the client to storage and back. Make it work before you make it scale.

    "A redirect hits the load balancer, then the redirect service, which checks the cache and falls back to the store on a miss."

  5. 05 · 14 min of 45 · 19 min of 60

    Deep dives

    Go deep on the 2 or 3 hardest parts: bottlenecks, consistency, hot spots and failures. Offer one yourself by about two thirds of the round, and name the trade-off of each choice.

    "The riskiest part is generating unique codes across many servers. Can I walk through two ways to do it and pick one?"

  6. 06 · 4 min of 45 · 5 min of 60

    Wrap up

    Recap the design against the requirements, name the trade-offs you made, and say what you would do next with more time: monitoring, cost, and what breaks at 10x.

    "We trade a little analytics freshness for fast redirects. At 10x, I would add a CDN for viral links and split analytics into its own pipeline."

Questions and answers

18 system design interview questions with answers

Each answer follows the six steps. The numbers are rounded estimates for the stated assumptions, which is exactly how you should present them in the room.

Reading the diagrams

Solid arrows are requests. Dashed arrows are background or async work. Boxes with a line under the top are databases, boxes with three ticks are queues or logs, and gray boxes are clients and outside services.

Checking the math

Every estimate uses 86,400 seconds in a day and decimal units. Try your own numbers in the back of the envelope estimator.

Practicing each one

All 18 are mock rounds in OphyAI System Design, on the Premium plan at 20 credits a round. Already a member? Open System Design.

Question 1 of 18ClassicStarter35 min mock round

1. URL shortener

Design a service that turns long links into short codes and redirects people who open them, at a high read volume.

Also asked as: Design a URL shortener · Design TinyURL · URL shortening service

What the interviewer is testing

Whether you can run the whole framework cleanly on a simple problem: a tidy API, a key scheme that never collides, and a read path built for caching. It is a starter question, so the bar is a complete, well-reasoned answer, not exotic tricks.

Requirements to clarify

  • How many new links a day, and how many clicks per link? That sets the read to write ratio.
  • Do people need custom aliases or expiry dates?
  • How short must the code be? Is it a problem if codes can be guessed?
  • Do we need click analytics, and how fresh?
  • Redirect with 301 (cached by browsers) or 302 (every click reaches us)?

Key numbers to estimate

New links100M a day
1.2k/s
Redirects100 reads per write, about 2x at peak
120k/s
Code space7 base62 characters
3.5 trillion
Storage5 years at 500 bytes a link
about 90 TB

Quick estimate

  1. Writes: 100M a day ÷ 86,400 s ≈ 1,160/s, call it 1.2k/s
  2. Reads: 100 × 1.2k ≈ 120k/s average, about 240k/s at a 2x peak
  3. Links in 5 years: 100M × 365 × 5 ≈ 183 billion
  4. Code length: 62^6 ≈ 57 billion (too few), 62^7 ≈ 3.5 trillion (plenty)
  5. Storage: 183B × 500 bytes ≈ 91 TB before replication

New to estimates? How to do a back of the envelope calculation

Core design

POST /urlsGET /:codesavelookupon missBrowserLoad balancerShorten serviceID generatorcounter rangesURL storekey-valueRedirect serviceURL cacheRedisClick eventsKafkaAnalytics
URL shortener: the main components and how requests flow. Dashed arrows are background or async work.

Components

  • Load balancer. Splits traffic between two stateless services, so reads and writes scale on their own.
  • Shorten service. Validates the URL, gets a new ID, base62-encodes it and saves the mapping.
  • ID generator. Hands out blocks of counter values to each Shorten node, so codes never collide.
  • URL store. A key-value store keyed by code, because every read is a lookup by one key.
  • URL cache. Redis in front of the store, cache-aside with LRU eviction. A small set of links gets most clicks.
  • Click events. Redirects emit a click event to a queue for analytics, off the hot path.

Data model

urls
code (PK), long_url, owner_id, created_at, expires_at
clicks
code, clicked_at, referrer, country (append-only, analytics store)

API

  • POST /urls {long_url, alias?, expires_at?} → {code}
  • GET /{code} → 302 with a Location header

Deep dives

Unique codes without collisions

Hashing the long URL (say MD5, keep 7 characters) needs a collision check and a retry, and the same URL always gets the same code. A counter never collides: each Shorten node leases a block of IDs, say 1,000 at a time, from a database sequence or a coordinator, then base62-encodes them. Counter codes are easy to guess; if that matters, scramble the ID with a reversible permutation before encoding. Custom aliases use a conditional write (insert only if absent).

Hot links and caching

Clicks follow a power law, so caching the most-clicked links catches most reads. If 20M links get most traffic, that is 20M × 500 bytes ≈ 10 GB, which fits in memory with room to spare. Use cache-aside with a TTL and LRU eviction, and put a CDN in front for viral links. A 301 is cached by browsers, which saves load but hides repeat clicks from analytics; a 302 keeps every click visible.

Expiry and cleanup

Store expires_at and check it on every read, so an expired link stops working right away even before cleanup. A background sweep deletes expired rows later to free space. Do not hand out expired codes again soon, or old links in emails and docs will point to someone else's page.

Common mistakes

  • Picking a hash function before sizing the key space.
  • Putting analytics writes on the redirect path, which slows every click.
  • Designing the write path in detail and barely touching the read path, which carries 100 times the traffic.
  • Choosing a store without tying it to the access pattern: every read is a lookup by key.
Mock round · Starter · 35 min

Practice it out loud

Draw it on a whiteboard while a voice AI interviewer asks follow-ups about your board, then get a Scorecard.

Practice this question
Question 2 of 18InfraCore45 min mock round

2. Rate limiter for a public API

Design a rate limiter for a public API that enforces per-customer limits across many servers and regions.

Also asked as: Design a rate limiter · API rate limiting · Distributed rate limiter

What the interviewer is testing

Your choice of algorithm and its trade-offs, atomic counters under concurrency, where the limiter sits in the request path, and what happens when the limiter itself fails. Strong answers keep the added latency to a couple of milliseconds.

Requirements to clarify

  • What do we limit on: API key, user, IP address, endpoint, or a mix?
  • What are the limits? For example 100 requests a second per key, with short bursts allowed.
  • Is a small overshoot acceptable, or must the limit be exact?
  • One region, or one global limit across regions?
  • What does a throttled client get? Usually 429 with Retry-After and rate limit headers.
  • If the counter store is down, do we fail open (allow) or fail closed (block)?

Key numbers to estimate

Peak trafficall customers, all regions
1M req/s
Counter shardsat about 100k ops/s each
about 10
Counter memory10M keys at about 100 bytes
about 1 GB
Added latencyat p99, in region
under 2 ms

Quick estimate

  1. Every request does one atomic read-modify-write: 1M ops/s at peak
  2. One Redis node handles roughly 100k simple ops/s: about 10 shards, plus replicas
  3. State per key: a token count and a timestamp, about 100 bytes with overhead
  4. Memory: 10M active keys × 100 bytes ≈ 1 GB, small enough to keep in memory
  5. An in-region round trip to Redis is well under 1 ms, inside the 2 ms budget

New to estimates? How to do a back of the envelope calculation

Core design

checktake tokenallowedlimitsthrottledAPI clientsAPI gatewayRate limitermiddlewareToken bucketsRedisBackend APIsLimit eventsKafkaRules serviceRules storePostgres
Rate limiter for a public API: the main components and how requests flow. Dashed arrows are background or async work.

Components

  • API gateway with limiter middleware. Every request is checked before it reaches the backend, so rejected traffic costs almost nothing.
  • Counter store. A Redis cluster sharded by key, holding token buckets or window counters with TTLs.
  • Rules service. Limits per plan and endpoint, stored in a database and cached in the middleware, so limits change without a deploy.
  • Limit events. Rejected requests go to a log or queue for dashboards and abuse detection.

Data model

bucket (Redis hash)
key rl:{api_key}:{endpoint} → tokens, last_refill_ms, TTL
rules
plan, endpoint, rate_per_sec, burst, updated_at

API

  • Middleware: allow(key, endpoint) → {allowed, remaining, reset_at}
  • Headers: X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After

Deep dives

Token bucket vs sliding window

Name the options, then pick one for this API and say why. For a public API that should allow short bursts, a token bucket per key is a strong default.

Rate limiting algorithms compared
AlgorithmHow it worksTrade-off
Fixed window counterOne counter per key per minute, reset at the boundary.Cheapest, but allows up to 2x the limit around a window edge.
Sliding window logStore each request time in a sorted set and count the last N seconds.Exact, but memory grows with traffic.
Sliding window counterWeight the previous window's count by how much it overlaps the current one.Close to exact with two counters per key.
Token bucketTokens refill at a steady rate up to a cap; each request takes one.Allows controlled bursts with two fields per key.
Leaky bucketRequests queue and drain at a fixed rate.Smooth output, but adds delay under load.

Race conditions

The classic bug: two servers both read "1 token left" and both allow the request. Do the refill, check and decrement in one atomic step, such as a Lua script in Redis, or INCR plus EXPIRE for a fixed window. Never read, decide and write back from the app server in separate calls.

Many regions and limiter failure

One global counter adds a cross-region round trip to every request. Instead give each region a share of the limit and sync usage in the background, accepting a small overshoot. If the counter store is down, fail open with a rough in-memory limit per server for most endpoints, and fail closed for abuse-prone ones such as login.

Common mistakes

  • Naming an algorithm without saying its trade-off.
  • Check-then-set logic that breaks when two requests arrive at once.
  • Keeping counters in each server's memory, so the real limit grows with the number of servers.
  • Forgetting the client side: 429, Retry-After and rate limit headers.
Mock round · Core · 45 min

Practice it out loud

Draw it on a whiteboard while a voice AI interviewer asks follow-ups about your board, then get a Scorecard.

Practice this question
Question 3 of 18ClassicCore45 min mock round

3. News feed

Design the home feed of a social network, where people see recent posts from the accounts they follow.

Also asked as: Design a news feed · Design the Twitter timeline · Design the Facebook news feed

What the interviewer is testing

Fan-out on write versus fan-out on read, the celebrity problem, caching a precomputed feed, and pagination. Interviewers want to see you land on a hybrid and explain exactly why.

Requirements to clarify

  • Chronological or ranked feed?
  • How many daily users, how many follows each, how many posts a day?
  • Are there accounts with millions of followers?
  • Do posts carry images or video?
  • How fresh must the feed be? Usually a few seconds of delay is fine.

Key numbers to estimate

Feed loadsabout 150k/s at peak
58k/s
New posts100M a day
1.2k/s
Fan-out writes200 followers on average
240k/s
Feed cache500 post ids per user
about 2 TB

Quick estimate

  1. Feed loads: 500M daily users × 10 a day = 5B ÷ 86,400 ≈ 58k/s
  2. Posts: 100M a day ÷ 86,400 ≈ 1.2k/s
  3. Fan-out: 1.2k posts/s × 200 followers ≈ 240k feed writes/s
  4. Feed cache: 500M users × 500 ids × 8 bytes ≈ 2 TB, spread over a Redis cluster
  5. Reads outnumber posts about 50 to 1, so precomputing feeds pays off

New to estimates? How to do a back of the envelope calculation

Core design

postget feedfollowerspush idsread idshydrateMobile appAPI gatewayPost servicePost eventsKafkaFan-out workersPost storewide-columnSocial graphFeed serviceFeed cacheRedis
News feed: the main components and how requests flow. Dashed arrows are background or async work.

Components

  • Post service. Saves posts to a post store partitioned by author; media goes to object storage behind a CDN.
  • Post events and fan-out workers. Each new post becomes an event; workers look up followers and push the post id into each follower's feed list.
  • Social graph. Who follows whom, indexed both ways.
  • Feed cache. A Redis list or sorted set per user with the newest few hundred post ids.
  • Feed service. Reads the id list, fetches the posts, merges in posts from big accounts, then ranks.

Data model

posts
post_id (time-sortable), author_id, text, media_urls, created_at
follows
follower_id, followee_id, created_at (indexed both ways)
feed:{user_id}
Redis sorted set of the last ~500 post ids, scored by time

API

  • POST /posts {text, media_ids}
  • GET /feed?cursor=&limit=20 → {posts, next_cursor}
  • POST /follows/{user_id}

Deep dives

Fan-out on write vs fan-out on read

This is the heart of the question. Push for normal accounts, pull for very large ones, and merge the two at read time. Skip pushing to users who have not opened the app in weeks; rebuild their feed if they come back.

Feed fan-out strategies compared
StrategyReadsWritesBest for
Fan-out on write (push)One cache lookupOne write per followerNormal accounts
Fan-out on read (pull)Merge many authors at read timeOne writeAccounts with millions of followers
HybridCache lookup plus a few pullsPush only below a follower thresholdThe usual answer

Ranking

Split it into candidate generation (recent ids from the feed cache plus pulled posts from big accounts) and a ranking step that scores a few hundred candidates with precomputed features. Keep a chronological fallback if ranking is slow or down.

Pagination and cold feeds

Page with a cursor on the post id or time, not an offset: new posts shift offsets and cause repeats or gaps. If a user's feed list was evicted, rebuild it on demand from the accounts they follow and write it back to the cache.

Common mistakes

  • Pure fan-out on write with no plan for accounts with millions of followers.
  • Copying whole posts into every feed list instead of ids.
  • Offset pagination on a feed that changes every second.
  • Serving images and video through the API servers instead of object storage and a CDN.
Mock round · Core · 45 min

Practice it out loud

Draw it on a whiteboard while a voice AI interviewer asks follow-ups about your board, then get a Scorecard.

Practice this question
Question 4 of 18Real-timeCore45 min mock round

4. Chat app

Design a chat app with one-to-one and group conversations, delivery receipts and online presence.

Also asked as: Design WhatsApp · Design Messenger · Design a chat system

What the interviewer is testing

Long-lived connections at scale, how a message finds the server that holds the recipient's connection, ordering within a conversation, delivery guarantees, and what happens when someone is offline.

Requirements to clarify

  • One-to-one only, or groups too? How large can a group be?
  • Text only, or images and files?
  • Read receipts, typing indicators, online presence?
  • History on several devices? How long do we keep it?
  • End-to-end encryption? It changes what the server can read and index.

Key numbers to estimate

Messagesabout 200k/s at a 3-4x peak
58k/s
Connectionsconcurrent, about 100 gateways
10M
Storageabout 180 TB a year
500 GB/day

Quick estimate

  1. Messages: 100M daily users × 50 = 5B a day ÷ 86,400 ≈ 58k/s
  2. Peak: about 3.5x average ≈ 200k/s
  3. Connections: 10% of daily users online at once = 10M; at 100k per gateway ≈ 100 gateways
  4. Storage: 5B × 100 bytes = 500 GB a day ≈ 180 TB a year, before replication

New to estimates? How to do a back of the envelope calculation

Core design

sendsaveheartbeatroutedeliverofflinePresence serviceChat appLoad balancerlayer 4GatewaysWebSocketChat serviceMessage storewide-columnConnectionsRedisMessage busKafkaPush serviceAPNs / FCM
Chat app: the main components and how requests flow. Dashed arrows are background or async work.

Components

  • Connection gateways. Hold one WebSocket per online device, behind a layer 4 load balancer.
  • Connection registry. Redis map from user to the gateway holding their connection, updated on connect and disconnect.
  • Chat service. Gives each message a sequence number for its conversation, saves it, then routes it to the recipients' gateways.
  • Message store. A wide-column store partitioned by conversation id and sorted by sequence, so history reads are one partition scan.
  • Presence and push. Heartbeats with a TTL for online status; push notifications for people who are offline.

Data model

messages
conversation_id (partition), seq (sort), client_msg_id, sender_id, body, sent_at
members
conversation_id, user_id, last_delivered_seq, last_read_seq
connections (Redis)
user_id → gateway_id, with a TTL

API

  • WebSocket: send {conversation_id, client_msg_id, body}
  • Server pushes: message, delivered ack, read ack, presence
  • GET /conversations/{id}/messages?before_seq=

Deep dives

Ordering in a conversation

Phone clocks drift, so never order by the sender's timestamp. The chat service assigns a sequence number per conversation (a counter stored with the conversation, or an atomic increment). Clients sort by it and can spot a gap and fetch what they missed.

Delivery guarantees and receipts

Aim for at-least-once delivery with dedupe. The sender retries until the server acks, and the client-made message id lets everyone drop duplicates. Delivered and read are acks flowing back: store last_delivered_seq and last_read_seq per member instead of a row per message per reader.

Large groups and offline users

For a group of thousands, fan out by gateway, not by person: send one copy to each gateway that holds members, and let it deliver locally. Offline members get a push notification, then sync from their last sequence number when they reconnect.

Common mistakes

  • Plain HTTP polling for real-time chat without discussing WebSockets or long polling.
  • Ordering by client timestamps.
  • No answer for how a message reaches the gateway that holds the recipient's connection.
  • A receipt row per message per reader in big groups.
Mock round · Core · 45 min

Practice it out loud

Draw it on a whiteboard while a voice AI interviewer asks follow-ups about your board, then get a Scorecard.

Practice this question
Question 5 of 18Real-timeAdvanced60 min mock round

5. Ride-hailing dispatch

Design the dispatch system for a ride-hailing app that matches riders to nearby drivers and tracks each trip live.

Also asked as: Design Uber · Design Lyft · Design a ride-sharing service

What the interviewer is testing

A geospatial index that takes a flood of location updates, matching a rider to a driver without double booking, live trip tracking, and sharding by geography.

Requirements to clarify

  • How many drivers online at peak, rides a day, cities?
  • How often do drivers send their location? Every 3 to 5 seconds is typical.
  • Match on nearest driver, fastest pickup, or something smarter?
  • Are surge pricing, shared rides and scheduled rides in scope? Usually not.
  • Target time from request to a driver accepting?

Key numbers to estimate

Location writes1M drivers, a ping every 4 s
250k/s
Ride requests20M rides a day
about 230/s
Match targetat p99
under 5 s
Geohash cellprecision 6
about 1.2 km

Quick estimate

  1. Locations: 1M drivers ÷ 4 s = 250k writes/s
  2. Rides: 20M a day ÷ 86,400 ≈ 230/s, several times that at rush hour
  3. Location writes are about 1,000x ride requests, so they go to an in-memory geo index, not the rides database
  4. Bandwidth: 250k × 50 bytes ≈ 12.5 MB/s, small in bytes but huge in operations

New to estimates? How to do a back of the envelope calculation

Core design

pingsrequestupdatefind drivernearbyETADriver appRider appAPI gatewayLocation serviceGeo indexin memoryMatching serviceMaps and ETARide serviceRidesPostgresRide eventsKafkaNotificationsWebSocket, push
Ride-hailing dispatch: the main components and how requests flow. Dashed arrows are background or async work.

Components

  • Location service. Takes driver pings and updates an in-memory geo index keyed by cell, sharded by region.
  • Ride service. Creates and tracks rides in a relational database and drives the ride state machine.
  • Matching service. Finds drivers in the rider's cell and its neighbors, ranks by ETA, and offers the ride to one driver at a time.
  • Maps and ETA. Road-network travel times; often an outside service.
  • Ride events and notifications. Status changes go to an event stream that pushes updates to both apps over WebSocket or push.

Data model

geo index (memory)
cell_id → {driver_id: lat, lng, updated_at}
driver_state
driver_id, status (available, offered, on_trip), ride_id, version
rides
ride_id, rider_id, driver_id, status, pickup, dropoff, fare, timestamps

API

  • PUT /drivers/{id}/location {lat, lng, ts}
  • POST /rides {pickup, dropoff} → {ride_id, status}
  • POST /rides/{id}/accept (driver)

Deep dives

The geo index

Geohash cells are string prefixes: easy to shard and look up, but a rider near a cell edge needs the 8 neighbor cells too. Quadtrees adapt to density but are costly to update 250k times a second. Hexagon grids such as H3 have even neighbor distances. With this write rate, a simple in-memory map from cell to drivers works well: move a driver between cells on each ping and drop entries that have not updated in, say, 30 seconds. Widen the search ring if too few drivers come back.

No double booking

Offer each ride to one driver at a time, with a short timeout (10 to 15 seconds). Claim the driver atomically: set status from available to offered only if it is still available, using SET NX with a TTL in Redis or UPDATE ... WHERE status = 'available' AND version = n. The TTL frees the driver if they never answer.

Sharding and hot spots

Shard the geo index and matching by city or region, since a ride almost never crosses regions. Airports and stadiums are hot cells with long lines of drivers; give them a first-in, first-out queue instead of a nearest-driver search.

Common mistakes

  • Writing every location ping to the main relational database.
  • Searching only the rider's own cell and missing a driver across the boundary.
  • Sending the ride to many drivers at once with no claim step, so two accept.
  • Ignoring stale positions from drivers who lost signal.
Mock round · Advanced · 60 min

Practice it out loud

Draw it on a whiteboard while a voice AI interviewer asks follow-ups about your board, then get a Scorecard.

Practice this question
Question 6 of 18PaymentsAdvanced60 min mock round

6. Payment ledger

Design a payment system with a ledger that charges cards, never loses or double counts money, and reconciles with the payment processor.

Also asked as: Design a payment system · Design a digital wallet · Design a ledger service

What the interviewer is testing

Correctness over raw speed: idempotent retries, double-entry accounting, side effects that happen exactly once (the outbox pattern), and reconciliation with an outside payment processor.

Requirements to clarify

  • Are we calling a payment service provider (PSP) to charge cards, or are we the processor? Usually we call a PSP.
  • Authorize and capture separately? Refunds? Payouts to sellers?
  • Peak payments per second?
  • Currencies? Store amounts as integers in the smallest unit (cents), never floats.
  • Audit and retention rules?

Key numbers to estimate

Peak paymentsa big holiday sale
10k/s
Ledger entriesper payment: every debit has a credit
2 or more
Ledger growth1B entries at 200 bytes
about 200 GB/mo
Idempotency windowcovers client retries
24 h or more

Quick estimate

  1. Peak: 10k payments/s × 2 entries = 20k ledger rows/s
  2. Monthly: 1B entries × 200 bytes ≈ 200 GB, about 2.4 TB a year
  3. That fits a sharded relational cluster for years; partition the ledger by time
  4. Idempotency keys: 10k/s × 86,400 s = 864M keys a day at peak rate, so give them a TTL

New to estimates? How to do a back of the envelope calculation

Core design

check keychargepostentriessettlementmatchMerchant clientsAPI gatewayIdempotency keysPayments servicePayment processorPSPReconciliationdaily jobsLedger serviceLedgerappend-onlyPayment eventsoutboxWebhooks
Payment ledger: the main components and how requests flow. Dashed arrows are background or async work.

Components

  • Payments service. Checks the idempotency key, records the payment as pending, calls the PSP to authorize and capture, and updates the status.
  • Ledger service. Writes balanced debit and credit entries to an append-only table, in the same transaction as the status change and an outbox row.
  • Outbox relay and events. Publishes committed outbox rows to an event stream for webhooks and other consumers.
  • Reconciliation jobs. Match the ledger against the PSP's daily settlement files and flag any break.

Data model

payments
payment_id, merchant_id, idempotency_key (unique per merchant), amount_minor, currency, status, psp_ref
ledger_entries
entry_id, txn_id, account_id, direction (debit, credit), amount_minor, created_at (never updated)
accounts
account_id, type (customer funds, merchant, fees), balance (derived)
outbox
event_id, type, payload, created_at, published_at

API

  • POST /payments {amount, currency, source, merchant_id} with an Idempotency-Key header
  • POST /payments/{id}/refunds
  • Webhooks: payment.succeeded, payment.failed, refund.succeeded

Deep dives

Idempotency end to end

The client sends an Idempotency-Key header. Store the key, a hash of the request body, the status and the response in the same database as the payment, under a unique constraint. A retry with the same key gets the stored response; the same key with a different body is an error. Send your own idempotency key to the PSP too, so a timeout on your side can be retried without charging twice.

Double-entry invariants

Every transaction is a set of entries that sum to zero: for a $100 charge with a $3 fee, debit customer funds 100, credit the merchant 97 and credit fees 3. Entries are never updated or deleted; a refund or a fix is a new transaction. Balances come from entries (or a cached balance updated in the same transaction), so the books can always be rebuilt and checked.

Exactly-once side effects and reconciliation

You cannot commit to a database and publish to a message stream in one atomic step. Write an outbox row in the same transaction, have a relay publish it, and make consumers dedupe by event id. Every day, match the ledger against the PSP's settlement file; fix each mismatch with an adjusting entry, never by editing history.

Common mistakes

  • Using floating-point numbers for money.
  • Retrying a charge without an idempotency key.
  • Updating a balance column in place with no entries behind it.
  • Publishing events outside the database transaction and hoping both succeed.
Mock round · Advanced · 60 min

Practice it out loud

Draw it on a whiteboard while a voice AI interviewer asks follow-ups about your board, then get a Scorecard.

Practice this question
Question 7 of 18StorageAdvanced60 min mock round

7. Video upload and streaming

Design a video platform where creators upload videos and viewers stream them smoothly on any device.

Also asked as: Design YouTube · Design Netflix · Design a video streaming platform

What the interviewer is testing

Keeping the upload and processing pipeline separate from playback, transcoding at scale, adaptive bitrate streaming, and showing with numbers why playback must come from a CDN.

Requirements to clarify

  • How many uploads a day, and how long and large is a typical video?
  • How many viewers, and how many watch at the same time at peak?
  • Which devices and quality levels, from 240p to 4K?
  • How soon after upload must a video be watchable?
  • Live streaming? Usually out of scope.

Key numbers to estimate

Uploadsof new video
500 h/min
Renditionsper video, 240p to 4K
about 6
Egress100M viewers at 5 Mbps
500 Tbps
Segmentsfor adaptive bitrate
2-10 s

Quick estimate

  1. Uploads: 500 hours a minute × 1,440 minutes ≈ 720k hours of video a day
  2. Storage: at about 5 GB an hour for all renditions ≈ 3.6 PB a day, before replication
  3. Egress: 100M viewers × 5 Mbps = 500 Tbps, which no single data center can serve
  4. So nearly all playback must come from CDN edge caches close to viewers

New to estimates? How to do a back of the envelope calculation

Core design

startpartssourcerenditionsreadyplayon missCreator appUpload serviceTranscode jobsqueueRaw uploadsobject storageTranscodersworkersVideo segmentsHLS / DASHCDNedge cachesMetadata serviceVideo metadataSQLViewer app
Video upload and streaming: the main components and how requests flow. Dashed arrows are background or async work.

Components

  • Upload service. Creates the video record and hands out presigned multipart upload URLs, so bytes go straight to object storage.
  • Transcode queue and workers. Split the source into chunks, transcode them in parallel into each rendition, and write segments plus a manifest.
  • Metadata service. Titles, owners, status and renditions in a database, plus a search index.
  • CDN. Serves manifests and segments from the edge, pulling from the segment store on a miss.

Data model

videos
video_id, owner_id, title, status (uploading, processing, ready, failed), duration, created_at
renditions
video_id, resolution, bitrate, codec, manifest_url
upload_parts
upload_id, part_number, etag, size

API

  • POST /videos → {video_id, upload_urls[]} (presigned, one per part)
  • POST /videos/{id}/complete
  • GET /videos/{id} → {title, status, manifest_url}

Deep dives

Resumable uploads

A 4 GB upload over a phone connection will drop. Split the file into parts (say 8 to 16 MB) and upload each to its own presigned URL. The client remembers which parts finished and resumes from there. Your API servers never touch the video bytes.

The transcoding pipeline

Transcoding a long 4K video in one job takes far too long. Split the source at keyframes, transcode the chunks in parallel across workers, then join them. Model the work as a small graph of steps (check, transcode each rendition, thumbnails, captions) on a queue with retries, and make every step safe to run twice.

Adaptive bitrate and the CDN

Each rendition is cut into 2 to 10 second segments listed in an HLS or DASH manifest. The player measures its throughput and switches rendition between segments, so playback adapts instead of stalling. Popular videos stay hot at the edge; even at a 99% CDN hit rate, origin still sends about 1% of 500 Tbps, which is why the origin tier is spread across regions.

Common mistakes

  • Sending video bytes through your API servers.
  • Forgetting that a video is not watchable the moment the upload ends.
  • Serving playback from origin with no CDN math.
  • Treating video bytes and video metadata as the same storage problem.
Mock round · Advanced · 60 min

Practice it out loud

Draw it on a whiteboard while a voice AI interviewer asks follow-ups about your board, then get a Scorecard.

Practice this question
Question 8 of 18ClassicCore45 min mock round

8. Web crawler

Design a web crawler that downloads about a billion pages a month for a search index while staying polite to every site.

Also asked as: Design a web crawler · Design a distributed crawler · Design a search engine crawler

What the interviewer is testing

The URL frontier, politeness per host, deduplication of both URLs and content, avoiding crawler traps, and how you spread the work over many machines.

Requirements to clarify

  • How many pages, and how fast? How often do we recrawl?
  • HTML only, or images and PDFs too?
  • Do we need to run JavaScript to render pages? It costs far more.
  • Politeness rules: robots.txt, crawl delays, requests per host?
  • Where do pages go next? Usually storage for an indexer downstream.

Key numbers to estimate

Pages1B a month, about 1k/s at peak
400/s
Raw storage100 KB a page
100 TB/mo
Politenessper host
1 req/s
Seen-URL filter10B URLs at 1% false positives
about 12 GB

Quick estimate

  1. Pages: 1B a month ÷ 2.6M seconds ≈ 400 pages/s
  2. Download: 400 × 100 KB = 40 MB/s, about 320 Mbps
  3. Storage: 1B × 100 KB = 100 TB a month of raw HTML, less once compressed
  4. Bloom filter: about 9.6 bits per URL at 1% false positives; 10B × 1.2 bytes ≈ 12 GB, which fits in memory

New to estimates? How to do a back of the envelope calculation

Core design

next URLGETHTMLsavelinksnewDNS cacheSeed URLsURL frontierper-host queuesFetchersThe webSeen URLsBloom filterParserlinks, fingerprintsPage storeobject storage
Web crawler: the main components and how requests flow. Dashed arrows are background or async work.

Components

  • URL frontier. Front queues by priority and back queues by host, with a scheduler that gives each host one fetcher at a time.
  • Fetchers. Download pages with timeouts, a DNS cache and a robots.txt cache per host.
  • Parser. Extracts links and text, normalizes URLs, and fingerprints the content.
  • Seen-URL filter. A Bloom filter or a key-value set of URL hashes, checked before a URL enters the frontier.
  • Page store. Object storage for pages, plus a table of URL state for recrawl scheduling.

Data model

url_state
url_hash (PK), url, host, last_fetched, content_hash, next_fetch_at, priority
pages
object key = url_hash + fetched_at, body compressed

API

  • Internal: enqueue(url, priority)
  • Fetch result: {url, status, headers, body, fetched_at}

Deep dives

The frontier and politeness

Front queues order URLs by priority, such as page importance and how stale they are. Back queues each hold one host. A heap keyed by "next time this host may be fetched" tells a free fetcher which back queue to take, which enforces about one request a second per host without slowing other hosts. Cache and obey robots.txt per host.

Duplicates

Normalize URLs before the seen check: lowercase the host, drop fragments and tracking parameters, sort query parameters. Mirrors and copies have different URLs but nearly the same content, so fingerprint pages with SimHash and treat a small Hamming distance as a duplicate.

Traps and freshness

Calendars and endless filter pages create infinite URLs. Cap depth, URL length and pages per host, and watch for repeating path patterns. Recrawl based on how often a page changed before: a news home page hourly, an old doc page monthly.

Common mistakes

  • One big FIFO queue, so one host gets hammered or the crawl stalls on slow hosts.
  • No URL normalization, so the same page is crawled many times.
  • Forgetting DNS, which can become the bottleneck.
  • Not saying where pages go and how the indexer reads them.
Mock round · Core · 45 min

Practice it out loud

Draw it on a whiteboard while a voice AI interviewer asks follow-ups about your board, then get a Scorecard.

Practice this question
Question 9 of 18InfraCore45 min mock round

9. Notification system

Design a notification system that sends push, email and SMS for many internal services, with user preferences and retries.

Also asked as: Design a notification service · Design a push notification system · Design an email and SMS service

What the interviewer is testing

Decoupling with queues, keeping urgent messages away from bulk ones, outside providers that rate-limit and fail, sending each notification once, and respecting user preferences.

Requirements to clarify

  • Which channels: push, email, SMS, in-app?
  • Transactional (one-time codes, receipts) versus marketing blasts? What priority does each get?
  • Volume per day, and the biggest blast?
  • Opt-outs, quiet hours, time zones?
  • Do we track sent, delivered and opened?

Key numbers to estimate

Daily volumeacross channels
about 1B
Average1B ÷ 86,400
12k/s
Blast peak10M in one minute
170k/s
Retry windowwith exponential backoff
up to 24 h

Quick estimate

  1. Average: 1B a day ÷ 86,400 ≈ 11.6k/s
  2. Blast: 10M ÷ 60 s ≈ 170k/s, about 15x average
  3. The queue absorbs the blast; workers drain it as fast as providers allow
  4. Providers cap your send rate, so a blast may take minutes: fine for marketing, not for login codes

New to estimates? How to do a back of the envelope calculation

Core design

sendcheckrecordPreferencesand templatesInternal servicesNotification APIDelivery logChannel queuesby priorityPush workersEmail workersSMS workersProviderspush, email, SMS
Notification system: the main components and how requests flow. Dashed arrows are background or async work.

Components

  • Notification API. Internal services call it with a user, a template, data, a priority and an idempotency key.
  • Preferences and templates. Checks opt-outs, quiet hours and channel choice, then renders the message.
  • Channel queues. Separate queues per channel and priority, such as codes, transactional and marketing.
  • Channel workers. Call the push, email or SMS provider, record the result, retry with backoff and dead-letter what keeps failing.
  • Delivery log. One row per notification with its status, used for dedupe and support.

Data model

notifications
notification_id, idempotency_key (unique), user_id, channel, template_id, status, attempts, created_at
preferences
user_id, channel, category, opted_in, quiet_hours, timezone
devices
user_id, device_token, platform, last_seen

API

  • POST /notifications {user_id, template_id, data, priority, idempotency_key}
  • GET /notifications/{id} → {status per channel}

Deep dives

No duplicate sends

Producers retry and queues deliver at least once, so duplicates will happen unless you stop them. Each notification carries an idempotency key, and the worker records it in the delivery log with a conditional insert before calling the provider. A crash between sending and recording can still double-send, so keep that window small and pass the provider an idempotency key where it supports one.

Priority and rate limits

Login codes and security alerts get their own queues and workers, so a marketing blast never delays them. Workers respect each provider's rate limit and a per-user cap, such as no more than a few marketing messages a day.

Provider failures

Retry with exponential backoff and jitter, and move a message to a dead-letter queue when its retry window ends. Keep a second provider per channel and switch when error rates climb. Treat "invalid token" errors from push providers as a signal to delete stale device tokens.

Common mistakes

  • One queue for everything, so a blast delays login codes.
  • Calling providers synchronously from the API.
  • No preference or quiet-hours check.
  • No idempotency, so retries spam people.
Mock round · Core · 45 min

Practice it out loud

Draw it on a whiteboard while a voice AI interviewer asks follow-ups about your board, then get a Scorecard.

Practice this question
Question 10 of 18ClassicCore45 min mock round

10. Search autocomplete

Design search autocomplete that suggests the top queries as someone types, for a search engine with billions of searches a day.

Also asked as: Design typeahead · Design search suggestions · Design an autocomplete system

What the interviewer is testing

A prefix index with the top results precomputed, very low latency at a very high read rate, and a pipeline that rebuilds the index offline while still catching trending queries.

Requirements to clarify

  • How many suggestions? Usually 5 to 10.
  • Ranked by popularity only, or personalized?
  • How fresh? Should a trending query show up within the hour?
  • Languages and spelling correction? Usually out of scope.
  • Do we filter offensive suggestions?

Key numbers to estimate

Suggest calls10B searches, 5 keystrokes each
600k/s
Latencyend to end, about 20 ms on the server
under 100 ms
Indextop 100M queries, sharded
tens of GB

Quick estimate

  1. Calls: 10B searches × 5 keystrokes = 50B a day ÷ 86,400 ≈ 580k/s
  2. Debouncing (wait about 100 ms after a keystroke) and caching cut that a lot
  3. Index: 100M queries × about 20 bytes = 2 GB of text, plus top-10 lists at every prefix: tens of GB
  4. That fits in memory on a few shards, with replicas for the read rate

New to estimates? How to do a back of the envelope calculation

Core design

prefixon misslookuploadBrowserdebounce, cacheEdge cacheshort prefixesSuggest serviceTrie shardstop 10 per prefixQuery logsAggregation jobcounts, decayTrie builderSnapshotsobject storage
Search autocomplete: the main components and how requests flow. Dashed arrows are background or async work.

Components

  • Client. Debounces keystrokes and caches results per prefix.
  • Edge cache. Caches the shortest, hottest prefixes for a short time.
  • Suggest service. Looks the prefix up in an in-memory trie or a prefix-to-top-10 map, sharded by prefix range.
  • Offline pipeline. Query logs, then an aggregation job (counts with time decay), then a trie builder that writes snapshots the servers load and swap.
  • Trending layer. A small streaming job over the last hour of queries, merged into results at read time.

Data model

prefix index
prefix → top 10 [(query, score)], precomputed
query_counts
query, window, count, last_seen

API

  • GET /suggest?q=new%20yo&limit=10 → [{query, score}]

Deep dives

Top results per prefix

Walking the trie below a short prefix such as "a" at request time is far too slow. Store the top 10 completions at every node, computed offline, so a lookup costs only the length of the prefix. Rebuild hourly or daily and swap snapshots in one step, so serving never waits on writes.

Freshness and trending

A batch index misses breaking news. Run a small streaming job over the last 10 to 60 minutes of queries and merge its top results with the batch list, weighted by a decay factor. Filter everything through a blocklist before it is served.

Sharding and hot prefixes

Shard by prefix range, but not by first letter alone: "s" is far bigger than "x". Split ranges by real traffic. One and two character prefixes are the hottest and change slowly, so cache them at the edge with a short TTL.

Common mistakes

  • Updating the serving trie on every search.
  • Walking the subtree at read time.
  • Sharding by first letter, which gives very uneven shards.
  • Ignoring client debouncing, which multiplies load.
Mock round · Core · 45 min

Practice it out loud

Draw it on a whiteboard while a voice AI interviewer asks follow-ups about your board, then get a Scorecard.

Practice this question
Question 11 of 18StorageAdvanced60 min mock round

11. File storage and sync

Design a file storage and sync service that keeps a person's files in sync across all their devices.

Also asked as: Design Dropbox · Design Google Drive · Design a file sync service

What the interviewer is testing

Keeping file bytes (blocks) apart from metadata, chunking and dedupe, uploading only what changed, handling conflicting edits, and telling other devices about changes quickly.

Requirements to clarify

  • Largest file size? Users, and devices per user?
  • Sharing and permissions? Version history?
  • Offline edits? Live co-editing is usually out of scope.
  • How fast should a change reach other devices?

Key numbers to estimate

Commits1B file changes a day
12k/s
Block sizeSHA-256 per block
4 MB
Dedupe savingsidentical blocks stored once
30% or more
Sync latencyto other devices
under 5 s

Quick estimate

  1. Commits: 1B changes a day ÷ 86,400 ≈ 11.6k/s, call it 12k/s
  2. Ingest: if a change uploads 100 KB of new blocks on average, 12k × 100 KB ≈ 1.2 GB/s, about 10 Gbps
  3. Stored: 100M users × 5 GB ≈ 500 PB, about 350 PB after 30% dedupe, before replication
  4. Metadata is small next to that, but it is where the hard consistency work lives

New to estimates? How to do a back of the envelope calculation

Core design

new blockscommitchangedpullDesktop clientchunk and hashBlock serviceBlock storeby SHA-256Metadata serviceMetadata DBshardedNotify servicelong pollOther devices
File storage and sync: the main components and how requests flow. Dashed arrows are background or async work.

Components

  • Desktop client. Watches folders, splits files into blocks, hashes them and asks which blocks the server lacks.
  • Block service and store. Stores blocks in object storage keyed by their hash, so identical blocks are stored once.
  • Metadata service. File tree, versions and block lists in a relational database sharded by user or shared folder.
  • Notification service. Long polling or WebSocket tells other devices that something changed; they then pull changes since their cursor.

Data model

files
namespace_id, file_id, path, latest_version
file_versions
file_id, version, block_hashes[], size, device_id, created_at
blocks
hash (PK), size, location, ref_count
journal
namespace_id, seq, change (drives each device's cursor)

API

  • POST /blocks/check {hashes[]} → {missing[]}
  • PUT /blocks/{hash}
  • POST /files/commit {path, base_version, block_hashes[]}
  • GET /changes?cursor= (long poll)

Deep dives

Chunking and delta sync

Fixed 4 MB blocks are simple, but inserting one byte near the start shifts every block after it. Content-defined chunking uses a rolling hash to pick block boundaries from the data itself, so an edit changes only a block or two. The client sends block hashes, the server replies with the ones it lacks, and only those upload.

Conflicts

Each commit names the version it was based on. If the server already has a newer version, the commit is rejected, and the client saves a "conflicted copy" instead of overwriting. Last writer wins quietly loses someone's work, which is a common wrong answer.

Metadata consistency

Upload blocks first, then commit the metadata that points to them, so no file ever points to a missing block. Blocks that nothing points to (failed uploads, versions past retention) are cleaned up later by reference counts or a mark-and-sweep job.

Common mistakes

  • Uploading the whole file again on every change.
  • Storing file bytes as blobs in the metadata database.
  • Last writer wins without saying it loses edits.
  • Every device polling the server every few seconds.
Mock round · Advanced · 60 min

Practice it out loud

Draw it on a whiteboard while a voice AI interviewer asks follow-ups about your board, then get a Scorecard.

Practice this question
Question 12 of 18Real-timeCore45 min mock round

12. Ticket booking with seat holds

Design a ticketing system for big concerts where fans pick seats, hold them for a few minutes and pay, during huge on-sale spikes.

Also asked as: Design Ticketmaster · Design a ticket booking system · Design a concert ticketing system

What the interviewer is testing

Correctness under contention (no seat sold twice), seat holds that expire on time, and surviving an on-sale spike far above normal traffic, usually with a waiting room.

Requirements to clarify

  • Reserved seats or general admission?
  • How long is a hold? Often 5 to 10 minutes.
  • The biggest on-sale: how many fans for how many seats?
  • Ticket limits per person? Bot protection?
  • What happens if payment succeeds just after a hold expires?

Key numbers to estimate

On-sale demandfor 50k seats in the first minute
10M fans
Hold timethen the seat is released
10 min
Seat map readsserved from cache
100k/s
Checkoutsadmitted users only
about 500/s

Quick estimate

  1. Arrivals: 10M fans in a minute ≈ 170k requests/s for the page alone, before refreshes
  2. Only 50k seats exist, so about 200 people want each seat
  3. Admit 30k users a minute from the waiting room ≈ 500 checkouts/s, a normal load for a booking service
  4. At about 2 tickets per order, the seats are gone within a couple of minutes

New to estimates? How to do a back of the envelope calculation

Core design

joinseat mapadmittedholdconfirmchargeFansCDNevent pagesWaiting roomadmission tokensSeat map cacheBooking serviceSeats DBsource of truthSeat holdsSET NX + TTLPayment provider
Ticket booking with seat holds: the main components and how requests flow. Dashed arrows are background or async work.

Components

  • CDN. Static event pages and seat map images, so the spike mostly hits the edge.
  • Waiting room. A virtual queue that admits users in batches with signed, short-lived tokens.
  • Booking service. Holds seats atomically, creates the reservation, calls payment and confirms the sale.
  • Seats database. The source of truth for each seat's status, in a relational database.
  • Seat holds and seat map cache. Optional fast gate in Redis, and a cached count of available seats per section.

Data model

seats
event_id, seat_id, status (available, held, sold), held_by, hold_expires_at, version
reservations
reservation_id, user_id, event_id, seat_ids, status (held, paid, expired), expires_at
tickets
ticket_id, reservation_id, seat_id, barcode

API

  • GET /events/{id}/seats → available seats per section
  • POST /holds {event_id, seat_ids, admission_token} → {hold_id, expires_at}
  • POST /holds/{id}/purchase {payment, idempotency_key}

Deep dives

No seat sold twice

Hold a seat in one atomic step: UPDATE seats SET status = 'held', held_by = ?, hold_expires_at = now() + 10 min WHERE seat_id = ? AND (status = 'available' OR (status = 'held' AND hold_expires_at < now())). Only one request can win. Confirm the sale the same way: UPDATE ... SET status = 'sold' WHERE status = 'held' AND held_by = ?. Redis SET NX with a TTL can sit in front as a fast gate, but the database row decides.

Seat-hold expiry

Expiry must work even if no cleanup job runs. Store hold_expires_at and treat an expired hold as available in every query, like the WHERE clause above; a sweeper only tidies rows and refreshes the seat map. Extend the hold briefly when payment starts, so nobody loses a seat mid-payment, and refund automatically if a payment lands after the seat was resold.

Waiting room and bots

Put fans in a queue before they reach the booking service, and admit them in batches at the rate checkout can handle. The admission token is signed and short-lived, so the booking service rejects anyone without one at almost no cost. Add bot checks before admission and limit tickets per account and per card.

Common mistakes

  • Check, then book: "is it free?" and "book it" as two separate queries.
  • A cron job as the only way holds expire.
  • Letting 10M fans reach the database at on-sale.
  • Trusting a cached seat map at booking time instead of the database.
Mock round · Core · 45 min

Practice it out loud

Draw it on a whiteboard while a voice AI interviewer asks follow-ups about your board, then get a Scorecard.

Practice this question
Question 13 of 18Real-timeCore45 min mock round

13. Real-time leaderboard

Design a real-time leaderboard for an online game with tens of millions of players that shows the top players and each player's rank.

Also asked as: Design a gaming leaderboard · Design a top-K leaderboard · Design a real-time ranking system

What the interviewer is testing

Sorted sets and their costs, rank queries on huge boards, sharding when one node is not enough, daily and weekly boards, and keeping scores honest.

Requirements to clarify

  • One global board, or also regional, friends, daily and weekly boards?
  • Players per board, and score updates per second?
  • Exact rank for everyone, or exact for the top and rough for the rest?
  • How are ties broken?
  • Who computes the score, the client or the game server?

Key numbers to estimate

Score updatesat peak, 500M a day
50k/s
Players per boardabout 5 GB in one sorted set
50M
Per updateabout 26 steps at 50M
O(log n)

Quick estimate

  1. Updates: 500M a day ÷ 86,400 ≈ 5.8k/s on average; evening peaks run much higher, so plan for 50k/s
  2. Memory: 50M players × about 100 bytes per sorted set entry ≈ 5 GB, fits on one node
  3. Cost: ZADD and ZREVRANK are O(log n); log2(50M) ≈ 26, so one node keeps up
  4. Reads: the top 100 is the hottest query, so cache it for a second or two

New to estimates? How to do a back of the envelope calculation

Core design

matchscoreZINCRBYtop, my rankZREVRANKGame clientGame serversvalidate resultsScore serviceScore historydurableLeaderboard APISorted setsRedis ZSET
Real-time leaderboard: the main components and how requests flow. Dashed arrows are background or async work.

Components

  • Game servers. Check match results and send score events. Never trust a score sent by the client.
  • Score service. Writes each score to durable history and updates the sorted sets with ZADD or ZINCRBY.
  • Sorted sets. One Redis sorted set per board and time window.
  • Leaderboard API. Top N with ZREVRANGE, a player's rank with ZREVRANK, and neighbors with a range around that rank.

Data model

lb:{board}:{window} (Redis)
sorted set: member = player_id, score = points with a tie-break
scores
player_id, match_id, points, created_at (durable history)

API

  • POST /scores {player_id, match_id, points} (from game servers)
  • GET /leaderboards/{board}/top?limit=100
  • GET /leaderboards/{board}/rank/{player_id}?around=5

Deep dives

Rank on huge boards

One sorted set handles tens of millions of players. Beyond one node, shard by score range: shard 1 holds the highest scores, and so on. A player's global rank is their rank inside their shard plus the size of every higher shard (ZCARD is O(1)). Rebalance the ranges as scores drift. For the long tail, a rough percentile ("top 12%") is often enough and far cheaper.

Daily and weekly boards

Use one key per window, such as lb:daily:2026-11-06 and lb:weekly:2026-W45, with a TTL a bit past the window's end. Each score update writes to every active window. If Redis loses a board, rebuild it from the durable score history.

Ties and cheating

Sorted sets break ties by member name, which is not fair. Fold time into the score, for example points × 10^10 + (a far-future timestamp - the time the score was reached), so whoever got there first ranks higher. Keep the result under 2^53, because Redis stores scores as doubles. Only game servers may submit scores.

Common mistakes

  • Sorting a SQL table on every request for the top 100.
  • Finding a rank by counting rows with higher scores.
  • Trusting scores sent by the game client.
  • No plan for daily and weekly resets.
Mock round · Core · 45 min

Practice it out loud

Draw it on a whiteboard while a voice AI interviewer asks follow-ups about your board, then get a Scorecard.

Practice this question
Question 14 of 18PaymentsCore45 min mock round

14. Hotel reservations

Design a hotel reservation system where guests search by dates and book rooms without overselling.

Also asked as: Design a hotel reservation system · Design a hotel booking system · Design Airbnb bookings

What the interviewer is testing

Modeling inventory per room type per night, concurrency on the last room, safe reserve-and-pay retries, and a read-heavy search path that may be a little stale while booking may not.

Requirements to clarify

  • Book a specific room, or a room type? Usually a room type.
  • Is overbooking allowed, and by how much?
  • Cancellations and refunds?
  • Search by city and dates, with filters?
  • Do hotels change their own rates and room counts?

Key numbers to estimate

Search vs bookabout 200 to 1
10k/s vs 50/s
Inventory rows1M hotels × 50 room types × 365 nights
about 18B
Overbookingonly if the hotel allows it
up to 5-10%

Quick estimate

  1. Bookings: 4M a day ÷ 86,400 ≈ 46/s, call it 50/s
  2. Searches: about 200x bookings ≈ 10k/s, served from a cache and a search index
  3. Inventory: 18B rows × about 50 bytes ≈ 900 GB; partition by hotel so a booking touches one shard
  4. Booking volume is tiny; the hard part is correctness, not throughput

New to estimates? How to do a back of the envelope calculation

Core design

searchbookreserveupdatechargeGuest appAPI gatewaySearch serviceAvailability indexcache, searchBooking serviceInventory DBper nightBooking eventsCDCPayment service
Hotel reservations: the main components and how requests flow. Dashed arrows are background or async work.

Components

  • Search service. Reads an availability index fed by booking events. It may lag a few seconds.
  • Booking service. Reserves every night of the stay in one transaction, then takes payment.
  • Inventory database. A relational database sharded by hotel_id, one row per room type per night.
  • Booking events. Change data capture from the inventory database keeps the availability index fresh.
  • Payment service. Charges with an idempotency key; pending reservations expire if payment never finishes.

Data model

room_type_inventory
PK (hotel_id, room_type_id, date), total_rooms, total_reserved, version
reservations
reservation_id (client-made), hotel_id, room_type_id, check_in, check_out, status (pending, confirmed, cancelled, expired), amount
rates
hotel_id, room_type_id, date, price

API

  • GET /search?city=&check_in=&check_out=&guests=
  • POST /reservations {reservation_id, hotel_id, room_type_id, check_in, check_out}
  • POST /reservations/{id}/pay {idempotency_key}

Deep dives

The last room

Two guests try to book the last room for the same nights. In one transaction run UPDATE room_type_inventory SET total_reserved = total_reserved + 1 WHERE hotel_id = ? AND room_type_id = ? AND date >= check_in AND date < check_out AND total_reserved < total_rooms (times 1.05 if the hotel allows 5% overbooking). If fewer rows changed than the stay has nights, roll back. Optimistic locking with a version column also works and suits low contention.

Reserve and pay safely

The client creates the reservation id when the booking page loads, so a double click or a retry maps to the same reservation. A reservation moves from pending (rooms held) to confirmed (paid) or expired (released by a timeout). The payment call carries its own idempotency key.

Search freshness

Search may show a room that just sold. That is fine as long as booking re-checks the source of truth. Feed the availability index from booking events, and cache popular city and date searches for a short time.

Common mistakes

  • One row per physical room per night when the hotel sells room types.
  • Checking availability in one query and booking in another with no condition or lock.
  • Sending search traffic to the transactional database.
  • No plan for pending reservations that are never paid.
Mock round · Core · 45 min

Practice it out loud

Draw it on a whiteboard while a voice AI interviewer asks follow-ups about your board, then get a Scorecard.

Practice this question
Question 15 of 18Real-timeAdvanced60 min mock round

15. Food delivery tracking

Design a food delivery service that takes orders, dispatches couriers and shows customers live tracking with an ETA.

Also asked as: Design DoorDash · Design Uber Eats · Design a food delivery app

What the interviewer is testing

An order state machine shared by three apps, sending the courier so they arrive when the food is ready, a heavy stream of location updates, and handling failures without stuck orders.

Requirements to clarify

  • Orders a day, and how big is the dinner peak?
  • How often do couriers send their location?
  • Can a courier carry two orders at once?
  • How accurate must the ETA be?
  • What happens when something goes wrong: who refunds, who reassigns?

Key numbers to estimate

Ordersat dinner peak, 5M a day
300/s
Location writes500k couriers, a ping every 5 s
100k/s
Tracking reads1M customers watching
200k/s
ETA targetof the real arrival
within 5 min

Quick estimate

  1. Orders: 5M a day ÷ 86,400 ≈ 58/s on average; meals bunch up, so plan for about 5x: 300/s
  2. Locations: 500k active couriers ÷ 5 s = 100k writes/s, the largest write load by far
  3. Tracking: 1M customers refreshing every 5 s = 200k reads/s, so push updates over WebSocket instead
  4. Orders are few but must be correct; locations are many but can be lossy

New to estimates? How to do a back of the envelope calculation

Core design

orderreadydispatchnearbypingspositionsETACustomer appOrder servicestate machineOrders DBRestaurant appDispatch serviceETA serviceprep + travelCourier appLocation serviceCourier geo indexin memoryTracking serviceWebSocket
Food delivery tracking: the main components and how requests flow. Dashed arrows are background or async work.

Components

  • Order service. Owns the order state machine and stores orders in a relational database.
  • Dispatch service. Picks a courier so they arrive about when the food is ready, and may batch two nearby orders.
  • ETA service. Combines prep time, travel time and history into a live ETA.
  • Location service and geo index. Courier pings go to an in-memory geo index, the same pattern as ride-hailing.
  • Tracking service. Pushes the courier's position and the ETA to the customer over WebSocket.

Data model

orders
order_id, customer_id, restaurant_id, courier_id, status, placed_at, ready_eta, delivery_eta
order_events
order_id, event_id (unique), from_status, to_status, at
courier positions (memory)
courier_id → lat, lng, updated_at, cell

API

  • POST /orders {restaurant_id, items, address, idempotency_key}
  • POST /orders/{id}/events {event_id, type} (accepted, ready, picked_up, delivered)
  • WebSocket: courier position and ETA for an order

Deep dives

When to dispatch

Send a courier the moment an order is placed and they wait at the restaurant; send one too late and the food goes cold. Estimate prep time from the restaurant's history and how busy it is now, add travel time, and assign so the courier arrives near the ready time. Batching two orders from nearby restaurants saves courier time, but only if neither ETA slips past its promise.

The order state machine

placed → accepted → preparing → ready → picked_up → delivered, plus cancelled and failed. Apply only allowed moves, each keyed by an event id, with UPDATE ... WHERE status = expected, so a retried event does nothing. This is what keeps three apps from disagreeing about one order.

Failures

A courier goes offline, a restaurant never accepts, a customer is not home. Put a timeout on each state that triggers an action: reassign the courier, cancel and refund, or alert support. Keep every transition, so support can see exactly what happened.

Common mistakes

  • Treating it as ride-hailing and ignoring prep time.
  • A free-form status field that any service can overwrite.
  • Every customer app polling for the courier's position.
  • No timeouts, so orders get stuck.
Mock round · Advanced · 60 min

Practice it out loud

Draw it on a whiteboard while a voice AI interviewer asks follow-ups about your board, then get a Scorecard.

Practice this question
Question 16 of 18InfraAdvanced60 min mock round

16. Distributed cache

Design a distributed in-memory cache that many services share.

Also asked as: Design a distributed cache · Design Memcached · Design a distributed key-value cache

What the interviewer is testing

Partitioning with consistent hashing, replication and failover, eviction, hot keys, and keeping the cache consistent with the database. Also knowing when a cache is the wrong tool.

Requirements to clarify

  • A pure cache (data can be lost) or a store that must persist?
  • Key and value sizes? Total working set?
  • Reads and writes per second?
  • Latency target? Usually under a millisecond in one region.
  • How stale may cached data be?

Key numbers to estimate

Throughputall services together
10M ops/s
Nodes100 TB at 256 GB a node
about 400
Virtual nodesper server on the ring
100-200
Latencyp99, same region
under 1 ms

Quick estimate

  1. Nodes: 100 TB ÷ 256 GB ≈ 390, about 400-500 with room for failover
  2. Load: 10M ops/s ÷ 400 nodes = 25k ops/s each, well inside one node's limit, so memory sets the node count
  3. Network: 10M × 1 KB = 10 GB/s, about 80 Gbps across the fleet, about 200 Mbps a node
  4. Adding one node to 400 moves only about 1/400 of the keys with consistent hashing

New to estimates? How to do a back of the envelope calculation

Core design

get, seton missringhealthApp servicesDatabasesource of truthCache clienthash ringCluster managermembershipCache node ACache node BCache node CReplicasone per node
Distributed cache: the main components and how requests flow. Dashed arrows are background or async work.

Components

  • Cache client. A library in each service that maps keys onto a consistent hash ring and talks to nodes directly.
  • Cache nodes. An in-memory hash table with TTLs and LRU or LFU eviction.
  • Replicas. One or more replicas per node for failover, and optionally for reads.
  • Cluster manager. Membership, the ring layout, health checks and replica promotion, often on top of a consensus store such as etcd or ZooKeeper.

Data model

entry
key, value, expires_at, size, LRU links
ring
virtual node hash → physical node

API

  • get(key) → value | miss
  • set(key, value, ttl)
  • delete(key)

Deep dives

Consistent hashing and rebalancing

With hash(key) mod N, adding one node remaps almost every key, the cache goes cold and the database gets flooded. On a hash ring, a key belongs to the next node clockwise, so adding or removing a node moves only about 1/N of the keys. Give each server 100 to 200 virtual nodes so load spreads evenly and a failed node's keys land on many servers, not one.

Hot keys

One viral key can overload one node however good the hashing is. Spot hot keys by sampling in the client, then keep them in a tiny local cache for a second or two, or copy them under several suffixed keys (key#1 to key#8) and read one at random.

Staying consistent with the database

Cache-aside is the default: read the cache, and on a miss read the database and fill the cache. On a write, update the database, then delete the cache key; deleting is safer than updating, which can race and leave old data. TTLs are the backstop. When a hot key expires, thousands of requests miss at once (a thundering herd); a lease lets one request refill it while the others wait or get the old value.

Common mistakes

  • Modulo hashing.
  • Updating the cache instead of deleting it, or doing it before the database write.
  • No plan for a node failure, when a cold cache floods the database.
  • Treating a cache as the source of truth with no persistence.
Mock round · Advanced · 60 min

Practice it out loud

Draw it on a whiteboard while a voice AI interviewer asks follow-ups about your board, then get a Scorecard.

Practice this question
Question 17 of 18InfraAdvanced60 min mock round

17. Metrics and alerting

Design a metrics and alerting platform that collects metrics from a million hosts, draws dashboards and pages on-call engineers.

Also asked as: Design a metrics monitoring system · Design a monitoring and alerting system · Design a time-series database

What the interviewer is testing

A write-heavy time-series pipeline, storage layout and compression, downsampling for long retention, control of series cardinality, and alerting that still works when ingest is struggling.

Requirements to clarify

  • How many hosts, and how many series per host? How often is each sent?
  • Retention: raw data for how long, rolled-up data for how long?
  • Queries: mostly dashboards over the last few hours, with rare queries over months?
  • How fast must an alert fire, and where does it go?
  • Do agents push, or do we scrape (pull)?

Key numbers to estimate

Active series1M hosts × 500 each
500M
Ingestone point per series every 10 s
50M points/s
Hot storageabout 1.4 bytes a point, compressed
about 6 TB/day
Alert checksper rule
every 30 s

Quick estimate

  1. Ingest: 500M series ÷ 10 s = 50M points/s
  2. Points a day: 50M × 86,400 ≈ 4.3 trillion
  3. Raw: 16 bytes a point (8 for time, 8 for value) ≈ 70 TB a day
  4. Compressed with delta-of-delta times and XOR values (the Gorilla approach): about 1.4 bytes a point ≈ 6 TB a day

New to estimates? How to do a back of the envelope calculation

Core design

pushblocksdownsamplereadrulespageHost agentsIngest gatewayseries limitsIngest logKafkaTSDB writersTime-series storehot + coldDashboardsQuery serviceRollup jobs1 min, 1 hourAlert evaluatorevery 30 sNotifierdedupe, route
Metrics and alerting: the main components and how requests flow. Dashed arrows are background or async work.

Components

  • Agents. Run on each host, batch points and push them (or a scraper pulls them).
  • Ingest gateways. Check data, enforce series limits per team, and write to a durable log partitioned by series.
  • Time-series writers and store. Buffer each series in memory, compress it, and flush time-partitioned blocks: recent data on SSD, old data in object storage.
  • Rollup jobs. Downsample to 1 minute and 1 hour for long retention.
  • Query service and alert evaluator. Dashboards query the store; the evaluator runs each rule on a schedule and sends firing alerts to a notifier that dedupes and routes them.

Data model

series
series_id = hash(metric + sorted tags), metric, tags
inverted index
tag=value → series ids
blocks
series_id, start, end, compressed points

API

  • POST /ingest [{metric, tags, ts, value}] (batched)
  • GET /query?expr=avg(cpu{service="api"})&from=&to=&step=
  • Alert rule: {query, threshold, for, severity, route}

Deep dives

Write path and storage layout

Hash the metric name plus its sorted tags into a series id. Points for a series arrive in time order, so buffer each series in memory for an hour or two, compress it, then write immutable blocks partitioned by time. A write-ahead log protects what is still in memory. Queries use an inverted index from tags to series ids.

Cardinality

One bad tag, such as a user id or request id, can turn one series into millions and take the store down. Cap new series per team and per metric, drop or reject unbounded tags at ingest, and show teams their own series counts.

Alerting you can trust

Alerts matter most when things are breaking, which is exactly when ingest lags. Give the evaluator its own path and treat missing data as an alert in itself. Require a condition to hold for a while before firing, to stop flapping, and group and dedupe notifications so on-call gets one page, not 500.

Common mistakes

  • Storing each point as a row in a relational database.
  • No downsampling, so a one-year query scans trillions of raw points.
  • Ignoring cardinality.
  • Alerting that goes quiet when data stops arriving.
Mock round · Advanced · 60 min

Practice it out loud

Draw it on a whiteboard while a voice AI interviewer asks follow-ups about your board, then get a Scorecard.

Practice this question
Question 18 of 18InfraAdvanced60 min mock round

18. Ad click aggregator

Design an ad click aggregator that counts clicks per ad per minute for billing and dashboards, without losing or double counting clicks.

Also asked as: Design an ad click aggregator · Design ad click event aggregation · Design real-time click counting

What the interviewer is testing

Stream processing with time windows, counts that are exact enough to bill on, late and duplicate events, hot keys, and a batch path that checks and corrects the stream.

Requirements to clarify

  • How fresh must dashboard counts be? And billing counts?
  • Which queries: per ad per minute, per campaign per hour, filtered by country?
  • How late can a click event arrive?
  • Must billing be exact, with fraud filtering?
  • Do clicks redirect through us, or are they logged some other way?

Key numbers to estimate

Clicksat peak, 10B a day
500k/s
Windowtumbling windows
1 minute
Late eventsallowed by the watermark
up to 5 min
Raw logat 200 bytes a click
2 TB/day

Quick estimate

  1. Average: 10B ÷ 86,400 ≈ 116k/s; plan for 4-5x at peak, about 500k/s
  2. Ingest: 500k × 200 bytes = 100 MB/s at peak, easy for a partitioned log
  3. Raw storage: 10B × 200 bytes = 2 TB a day, kept for audits and replays
  4. Aggregates: if 1M ads get clicks in a minute, that is 1M rows a minute, about 1.4B a day; roll up to hourly after a week

New to estimates? How to do a back of the envelope calculation

Core design

clickupsertarchivecorrectqueryUser browserClick servicelog + redirectClick logKafkaStream aggregator1 min windowsAggregatesOLAP storeRaw clicksobject storageBatch recountdailyDashboards
Ad click aggregator: the main components and how requests flow. Dashed arrows are background or async work.

Components

  • Click service. Gives each click a unique id, writes it to the click log and redirects the user.
  • Click log. A partitioned, replayable log such as Kafka, keyed by ad_id.
  • Stream aggregator. A stream processor such as Flink: dedupes by click id and counts per ad per minute by event time.
  • Aggregate store. An analytics (OLAP) database that serves dashboard queries.
  • Raw store and batch recount. Every click in object storage; a daily job recounts and corrects the stream for billing.

Data model

click event
click_id, ad_id, campaign_id, device_hash, event_time, ip, country
ad_clicks_minute
PK (ad_id, minute), clicks, updated_at

API

  • GET /click?ad_id=&redirect= → 302 to the advertiser, after logging
  • GET /stats?ad_id=&from=&to=&granularity=minute

Deep dives

Exactly-once counts

The log delivers at least once, and the click service may retry. Give each click a unique id at the edge and dedupe in the stream job, keeping seen ids in keyed state a little longer than the lateness window. Checkpoints save that state together with the log offsets, and results are written idempotently (upsert by ad_id and minute), so a restart replays without double counting. At peak, 10 minutes of ids is 500k × 600 ≈ 300M ids, about 5 GB at 16 bytes each, spread across the job.

Late and out-of-order events

Window by event time, not arrival time. A watermark tracks how far event time has moved; a window closes once the watermark passes its end plus the allowed lateness (say 5 minutes). Events later than that go to a side output, and the daily batch recount folds them in.

Hot ads

A big campaign can send a large share of all clicks to one key and swamp one partition. Salt the key (ad_id#0 to ad_id#15) to spread it over partitions, count each part, then merge the partial counts. Or pre-aggregate for a second in the click service before sending.

Common mistakes

  • Incrementing a database counter on every click.
  • Windowing by processing time.
  • Claiming exactly-once without saying how dedupe and checkpoints work.
  • No raw log, so a bug in the stream job cannot be fixed by replaying.
Mock round · Advanced · 60 min

Practice it out loud

Draw it on a whiteboard while a voice AI interviewer asks follow-ups about your board, then get a Scorecard.

Practice this question
Cheat sheet

System design cheat sheet: building blocks and when to use them

The parts you will reach for in almost every answer, when each one fits, and the catch to mention before the interviewer does.

Building blockUse it whenWatch out for
Load balancerSpread traffic over stateless servers. Layer 4 for raw connections such as WebSockets; layer 7 to route by path or header.Sticky sessions hide state in servers. Use health checks and drain connections during deploys.
CDNStatic files, images, video segments and cacheable responses, served close to users.Purging is slow, so put a version in file names. Be careful with per-user data.
CacheReads far outnumber writes and a small hot set gets most traffic. Cache-aside is the default.Stale data, hot keys, and herds of misses when a hot key expires. Delete on write and set TTLs.
Message queue or logDecouple slow work, absorb spikes and fan out events. A log such as Kafka when you need order per key and replay.Delivery is at least once, so consumers must be idempotent. Watch consumer lag.
ShardingData or writes no longer fit on one machine. Hash for an even spread, range for scans, geography for locality.Hot shards, queries that span shards, and resharding. Consistent hashing limits how much data moves.
ReplicationSurvive machine loss and scale reads. Leader and followers is the default; multi-leader or leaderless for writes in many regions.Replica lag: a read right after a write can be stale. Async failover can lose the latest writes.
Consistency choicesStrong consistency for money, inventory and anything unique. Eventual consistency for feeds, counters and analytics.During a network partition you pick consistency or availability (CAP). In leaderless stores, R + W > N gives overlapping quorums.
SQL or NoSQLSQL for relations, transactions and flexible queries. Key-value or wide-column stores for huge scale with simple access by key.Choose from the access pattern, not fashion. Both kinds can be sharded.
Object storageLarge files: photos, video, backups and logs. Cheap and durable; serve it through a CDN.Not for small, frequent updates. Use presigned URLs so clients upload directly.
Rate limitingProtect services from abuse and overload. A token bucket per key at the gateway is the usual answer.Counters must be atomic in a shared store. Decide whether to fail open or closed.
IdempotencyAny retried write that must happen once: payments, orders, bookings, notifications.Store the key and the result in the same transaction as the write, and keep keys for a set window.
Search indexFull-text search, filters and ranking across many fields.It is not the source of truth. Feed it from the main store with events or change data capture.
Real-time pushChat, live tracking, notifications and live dashboards, over WebSockets, server-sent events or long polling.Connections are stateful, so you need a registry of which server holds each user.
Unique IDsTime-sortable IDs (timestamp, machine id and a sequence) for posts, messages and events.Clock skew between machines. Auto-increment does not work across shards.
Bloom filterCheap "have I seen this before?" checks, such as crawled URLs.False positives are possible, false negatives are not. A plain one cannot delete.
Geo indexFind things near a point: drivers, couriers, stores. Geohash, quadtree or hexagon cells.Search neighboring cells too, and use smaller cells where it is dense.
Outbox or change data capturePublish an event reliably after a database write, without a two-system commit.Consumers must dedupe by event id.

Numbers to keep handy

seconds in a day, round to 100k
86,400
requests a day to requests a second
1M/day ≈ 12/s
bits to bytes: divide by 8
1 Gbps = 125 MB/s
memory · SSD random read · cross-continent round trip
100 ns · 150 µs · 150 ms

The full list, with powers of two and latency numbers, is in our back of the envelope calculation guide.

Prep plan

How to prepare for a system design interview in 2 to 4 weeks

An hour or two a day is enough. Practice out loud and against a timer, because the round tests how you explain as much as what you know.

  1. Week 1

    Foundations

    • Learn every building block in the cheat sheet, and one trade-off for each.
    • Learn the 6 steps and their time targets until they are automatic.
    • Do a 10 minute estimation drill each day.
    • Do the URL shortener and the rate limiter on paper, out loud, against a timer.
  2. Week 2

    The core classics

    • News feed, chat app, web crawler, notification system and search autocomplete.
    • Ticket booking, leaderboard and hotel reservations.
    • One question a day for 45 minutes, then compare with the notes on this page.
    • Keep a list of the deep dives you could not explain, and look them up.
  3. Week 3

    The advanced set

    • Ride-hailing dispatch, payment ledger, video upload and streaming, file storage and sync.
    • Food delivery tracking, distributed cache, metrics and alerting, ad click aggregator.
    • Use 60 minutes for these, as the real round often does.
    • Read about one real system for each pattern: sharding, stream processing, consensus.
  4. Week 4

    Mock rounds

    • Run 3 to 5 full mock rounds with a person or an AI interviewer.
    • Use the whiteboard tool you expect in the real round.
    • After each one, note where you ran long and what you missed.
    • Redo your two weakest questions from scratch.

Only have 2 weeks?

Week 1: the building blocks, the six steps, daily estimates, and six core questions (URL shortener, rate limiter, news feed, chat app, notification system, ticket booking). Week 2: four advanced questions (payment ledger, ride-hailing dispatch, distributed cache, ad click aggregator) and three or four full mock rounds.

Habits that matter most

  • Talk while you draw. Silence reads as being stuck.
  • Drive the round: propose the next step instead of waiting to be asked.
  • Tie each choice to a requirement or a number.
  • Name the trade-off of every big choice before the interviewer does.
  • Check in at the end of each step: "Does this look right before I go deeper?"
Practice

Practice these questions with OphyAI System Design

OphyAI System Design helps in the real system design round and in practice: a Live Copilot that tells you what to say and draw next, and full mock rounds on a whiteboard with a voice AI interviewer and a scorecard.

Mock round · 20 credits

A full round on a whiteboard

A Mock round is a 35 to 60 minute practice round on a built-in whiteboard. A voice AI interviewer asks follow-ups about what you drew, and you can ask for up to 3 hints.

Every mock ends with a Scorecard: a 0 to 100 score, 7 skill scores, your time on each step against a target, 3 fixes, your board next to a strong answer's board, and the key moments of the round.

The Scorecard is an AI estimate. The bar for your level (80 for Senior) is OphyAI's own benchmark, not any company's hiring bar.

Start a mock round
Live Copilot · 30 credits

Help in the real round

Live Copilot listens to the interviewer on your call and reads your whiteboard from a shared tab or window, or a phone photo. It keeps one design plan (requirements, estimates, API and data, a boxes-and-arrows diagram, deep dives) and for each question gives a short "Say this now" answer, what to draw next, the key number to mention, and how to handle pushback.

System Design is on the Premium plan ($59 a month, 500 credits): 30 credits a live session and 20 credits a practice round.

See how System Design works

System design interview questions: FAQ

What are the most common system design interview questions?

The classics come up again and again: design a URL shortener, a rate limiter, a news feed, a chat app, ride-hailing dispatch, a payment ledger, video upload and streaming, a web crawler, a notification system, search autocomplete, file storage and sync, ticket booking with seat holds, a real-time leaderboard, hotel reservations, food delivery tracking, a distributed cache, metrics and alerting, and an ad click aggregator. Each one tests a different core idea, such as caching, fan-out, idempotency or stream processing, so practicing all of them covers most of what you will be asked.

How do you answer a system design interview question?

Use the same six steps every time: clarify the requirements, estimate the scale, write the API and data model, draw the high-level design, go deep on the two or three hardest parts, then wrap up with the trade-offs you made. Say your assumptions out loud, check in with the interviewer at each step, and tie every choice back to a requirement or a number.

How long is a system design interview, and how should I split the time?

Most system design rounds run 45 to 60 minutes. For 45 minutes, a good split is about 5 minutes on requirements, 4 on estimates, 6 on the API and data model, 12 on the high-level design, 14 on deep dives and 4 to wrap up. For 60 minutes, scale each step up: about 7, 5, 8, 16, 19 and 5 minutes. Offer your first deep dive by about two thirds of the way in.

How do I prepare for a system design interview?

Give yourself 2 to 4 weeks. Learn the building blocks first (caches, queues, sharding, replication, consistency, CDNs), then practice the classic questions out loud against a timer, two or three a week at first. Do a short estimation drill most days. In the last week, run full mock rounds on the whiteboard tool you expect to use, and redo the questions where you ran out of time.

What do interviewers look for in a system design interview?

They look for clear requirements before any drawing, numbers that drive decisions, a simple design that works end to end, depth on the hard parts, honest trade-offs, and clear communication. There is rarely one right answer. A reasonable design you can defend beats a fancy one you cannot explain.

Do I need to do math in a system design interview?

Only rough math. You estimate requests per second, storage and bandwidth to the nearest power of ten or so, using round numbers such as 100,000 seconds in a day. The point is what the numbers mean for the design, such as needing a cache or sharding the database. See our back of the envelope calculation guide for the method and a free estimator.

What is the difference between a mid-level, senior and staff system design answer?

Mid-level answers are expected to reach a working design with sensible components and some trade-offs. Senior answers drive the round, size the system with numbers, and go deep on bottlenecks, consistency and failure handling without being led. Staff answers also handle more ambiguity, weigh cost and operations, explain how the design evolves over time, and spot the risks that matter most.

Do new grads and junior engineers get system design interviews?

Sometimes, but it is less common, and the bar is lower. Junior candidates more often get object-oriented design or a lighter design discussion. Full system design rounds are most common from mid-level up. It still helps to know the basics, such as caching, load balancing and databases.

What should be on a system design cheat sheet?

The building blocks and when to use each one: load balancers, CDNs, caches, message queues, sharding, replication, consistency choices, SQL versus NoSQL, object storage, rate limiting, idempotency, search indexes and real-time connections. Add the numbers you will need for estimates, such as 86,400 seconds in a day and the common latency numbers. The cheat sheet on this page covers all of it.

Can I practice system design interviews with AI?

Yes. OphyAI System Design has mock rounds for all 18 questions on this page: a 35 to 60 minute practice round on a built-in whiteboard with a voice AI interviewer who asks follow-ups about what you drew, and up to 3 hints. Every round ends with a Scorecard: a 0 to 100 score, 7 skill scores, your time on each step against a target, 3 fixes and your board next to a strong answer. The Scorecard is an AI estimate, and its bar is OphyAI's own benchmark. System Design is on the Premium plan ($59 a month), and a mock round uses 20 credits.

Practice the round out loud before the real one

Pick any of the 18 questions, draw it on a whiteboard, and answer follow-ups from a voice AI interviewer. System Design is on the Premium plan.