Blog
System design, written down properly
Walkthroughs, interview problems and engineering notes. Every post is built from something that was actually measured or built, not summarised from elsewhere.
Roni Das
Founder, systemdesign.academy
90 posts · page 4 of 5
Online Judge System Design Interview: Running Untrusted Code Safely at Contest Scale
An online judge accepts source code, runs it against a set of hidden test cases, and returns a verdict such as Accepted, Wrong Answer, Time Limit Exceeded, or Memory Limit Exceeded. The hard part is not the web app. It is executing untrusted code safely and cheaply at high concurrency. A submission is accepted quickly, persisted, and dropped onto a queue, then a pool of judge workers pulls jobs and runs each one inside a locked-down sandbox with hard limits on CPU time, wall time, memory, process count, and output size. The judge compiles the code, runs it test by test against stored inputs, compares output to the expected answer with a checker, and emits the first failing verdict. Results flow back through a results channel that the client polls or receives over a websocket. The interesting design pressure comes from contests, where a synchronized burst of submissions creates a thundering herd on the queue and the worker pool, and from security, where a single sandbox escape leaks every hidden test on the machine. Good answers treat isolation, back-pressure, and fair scheduling as first-class, not as an afterthought.
readPayPal System Design Interview: Moving Money Exactly Once Without Ever Losing a Cent
PayPal is a consumer wallet, a peer-to-peer transfer network, and a checkout processor stacked on top of one money movement core. The center of the design is a double-entry ledger where every transaction writes balanced debit and credit entries that always sum to zero, and ledger rows are append-only so history can never be rewritten. Money movement demands strong consistency and ACID transactions rather than eventual consistency, because a lost or duplicated balance update is real money gone. Every write is made idempotent with a client-supplied request id so retries after a timeout do not move money twice. Flows that touch several services, for example debiting a wallet, running risk, and settling to a bank, are coordinated with sagas and compensating entries instead of a single global lock. Around the ledger sit real-time fraud and risk scoring in the authorization path, holds and authorization versus capture semantics, refunds, chargebacks and reversals, multi-currency balances with foreign exchange, and continuous reconciliation against banks and card networks. The interview is really about correctness under partial failure at high volume, not raw throughput.
readPaytm System Design Interview: UPI, Ledgers, Idempotency
Designing Paytm is the canonical India payments problem. You have to move real money between two banks over the NPCI UPI rails, keep a double-entry ledger that always balances, make every operation idempotent so a retry never double-charges, reconcile against the bank end-of-day, and survive a Diwali sale spike that is 5 to 10x a normal Tuesday. It is less about clever algorithms and more about correctness under failure.
readPhonePe System Design Interview: UPI at National Scale
Designing PhonePe is the India payments problem at national scale. You have to move real money over the NPCI UPI rails without ever creating or losing a rupee, make every step idempotent so a retry never double charges, and reconcile against the bank when a callback arrives late. On top of that correctness core, PhonePe is a study in scaling: a shared-nothing sharded MySQL ledger, an Aerospike layer serving real-time reads and fraud checks at very high throughput, a Kafka backbone carrying about 100 billion events a day, and its own on-premises data centers. The interview is as much about horizontal scale and availability as it is about money.
readPinterest System Design Interview: Visual Discovery, the Pin-Board Graph, and Recommendations at Scale
Pinterest is a visual discovery engine. A pin is an image with a link and metadata, a board is a themed collection, and users save pins onto boards and follow other users and boards. The hard part is not storing pins, it is discovery: given a person or an image, find the most relevant pins out of billions in tens of milliseconds. The core data lives in heavily sharded MySQL where every object carries a 64-bit ID that encodes its shard, and all cross-object relationships are resolved with application-layer joins backed by memcache and Redis rather than SQL joins. On top of that sits a home feed built by a Smart Feed pipeline that generates candidates, scores them with a ranking model, and materializes a frozen view so the feed stays available even when a generator is slow. The recommendation core is graph-based: Pixie runs biased random walks over the pin-board graph in real time, and PinSage learns pin embeddings with a graph convolutional network so related pins can be retrieved by approximate nearest neighbor. Visual search adds a unified image embedding so a crop of an image maps to visually and semantically similar pins. Everything is read heavy, so caching and CDN image delivery matter as much as the models.
readRapido System Design Interview: Bike-Taxi Dispatch at Scale
Designing Rapido is a ride-hailing problem with two things that make it distinct. First, the core vehicle is a two-wheeler, and Rapido has published how it matches riders to nearby bikes, moving from a simple radius-and-straight-line approach to hex-grid geography with learned driving times. Second, the money model is different: rather than taking a commission on each ride, Rapido charges captains a flat subscription and lets them keep the full fare, which changes the settlement path from a per-ride commission ledger to a subscription-entitlement check. This walkthrough covers the two-wheeler dispatch that Rapido has published, the subscription money model and its system implications, and the data platform behind it, and is honest about which parts are published versus reasoned.
readRate Limiter System Design Interview: Counting Requests Correctly Across a Fleet
The job sounds trivial, count requests per key and reject once the count crosses a limit, but almost everything hard is hidden in that sentence. You have to decide what a key is (user, IP, API key, or a tuple of endpoint and user), where the check runs (client, gateway, or service), and which algorithm to use (fixed window, sliding window log, sliding window counter, leaky bucket, or token bucket), each with a different memory and burst profile. The moment you run more than one limiter node, the counter has to live in shared state, usually Redis, and the read-modify-write becomes a race condition that lets requests slip through unless you make it atomic with a Lua script or an atomic INCR. Then you decide what happens when the shared store is slow or down, fail open and let traffic through, or fail closed and reject. On top of that you owe the caller a clean contract: a 429 status, a Retry-After header, and headers that tell them how many calls remain. A good answer treats the algorithm as the easy part and spends its time on atomicity, propagation delay, burst handling, and the failure modes.
readRecommendation System Design Interview: Two-Stage Candidate Generation and Ranking at Billion-Item Scale
The interview is really about a funnel. You cannot score billions of candidate items with an expensive model on every request, so you split the work into stages. A retrieval or candidate generation stage cuts the catalog from billions down to a few hundred or a few thousand cheaply, usually with a two-tower model whose item embeddings are precomputed and indexed for approximate nearest neighbor search. A ranking stage then scores that short list with a heavier model that can afford richer user-item cross features. Behind both sits a feature store that serves the same feature values online at request time and offline during training, so the model sees consistent inputs. A streaming pipeline turns clicks, watches, likes, and skips into fresh features and training labels. The recurring themes an interviewer probes are the latency budget across stages, how you keep offline and online features in sync, how you handle cold start for new users and new items, and how you measure whether a change actually helped through A/B testing rather than offline metrics alone.
readReddit System Design Interview: Comment Trees, Vote Ranking, and Cached Listings at Scale
A Reddit clone looks simple until you open a busy thread. The core objects are posts, comments, votes, and subreddits, but comments form arbitrarily deep trees that must be stored, ranked, and paginated with a working 'load more comments' path. Ordering is driven by three real algorithms: hot uses a logarithmic vote weight plus a time term so fresh content floats up, best uses the Wilson score lower confidence bound so a comment with 10 of 10 upvotes does not outrank one with 400 of 420, and controversial rewards posts where ups and downs are close and both large. Votes arrive faster than any single Postgres row can absorb, so counting is asynchronous and cached, and Reddit historically fuzzed vote totals to frustrate spam bots. Reads dominate writes by a wide margin, so subreddit and home listings are precomputed and cached rather than queried live. The interesting failure mode is a hot post: a single key gets so much traffic that a cache miss can stampede the origin. Reddit's real history, a schemaless 'thing' plus 'data' store on Postgres, heavy Cassandra use, memcached everywhere, and RabbitMQ for async work, gives you a concrete blueprint to reason from.
readRedis System Design Interview: Building a Single-Threaded In-Memory Data Store That Serves Millions of Ops per Second
Redis is an in-memory data structure store that people reach for as a cache, but it is really a small, fast database with server-side data types: strings, hashes, lists, sets, sorted sets, streams, bitmaps, and HyperLogLog. The core is a single-threaded event loop that processes commands sequentially, which removes lock contention and makes every operation effectively atomic without the programmer thinking about it. Because data lives in RAM, latency is dominated by the network round trip rather than disk. Durability is optional and tunable through two mechanisms: point-in-time RDB snapshots and an append-only file (AOF) that logs every write. Availability at scale comes from asynchronous primary-replica replication plus either Redis Sentinel for automatic failover of a single shard, or Redis Cluster, which shards the keyspace across 16384 hash slots and gossips membership between nodes. The hard design questions are all trade-offs: how much data you are willing to lose on a crash or failover, how you handle multi-key operations once keys live on different shards, and whether you can tolerate reading slightly stale data from a replica. Redis leans AP: it favors staying available and fast over guaranteeing that every replica is perfectly in sync.
readSearch Autocomplete (Typeahead) System Design Interview
A typeahead system suggests the most likely completions for whatever prefix a user has typed so far, and it does this on every keystroke. The read path must be extremely fast because a suggestion has to come back before the user types the next character. The core trick is a trie (prefix tree) where each node stores the precomputed top-k completions for that prefix, so a lookup is O(length of the prefix) instead of a scan. Popularity comes from an offline pipeline that mines historical query logs and rebuilds the trie on a schedule. A separate fast path layers recent trends on top so spikes show up without waiting for the next full rebuild.
readSharded Counters: Distributed Counter System Design
A distributed counter looks trivial until you notice that popularity is not evenly distributed. Most counters are cold, but a handful go viral and take a firehose of concurrent increments. The core problem is write contention on a single hot key, because consistent hashing maps one key to exactly one node no matter how large the cluster is. The standard answer is to stop storing the count as one value. You either shard the counter into N sub-counters and sum them on read, buffer increments in memory and flush batched deltas, or model the counter as a CRDT so replicas merge without coordination. Reads and writes get very different treatment: writes must be cheap and absorb bursts, while reads tolerate a slightly stale number because nobody notices if a like count is off by a few for a second. For unique counts like distinct viewers you switch to a probabilistic structure such as HyperLogLog. Durability comes from a persistent store behind a fast cache, and time-windowed counts fall out of bucketing events by time. The whole design is an exercise in trading exact, immediate consistency for write throughput and availability.
readSlack System Design Interview: Real-Time Messaging for Millions of Persistent Connections
Slack is a persistent-connection problem wearing a chat app's clothes. Every logged-in client holds a WebSocket to a gateway server, and the server pushes a stream of events for the channels that client cares about. On top of that live socket you layer a normal request/response web tier for sending messages, editing, and search, plus a durable store for message history. The design splits cleanly into three planes: a real-time delivery plane built on WebSockets and a gateway fleet, an application plane of stateless web servers that write to sharded MySQL through Vitess, and an edge caching plane called Flannel that keeps hot workspace metadata (users, channels, bots) close to clients so boot and reconnect stay cheap. The interview rewards candidates who separate ephemeral state (presence, typing) from durable state (messages, membership), who shard message storage by channel rather than by whole workspace to avoid hot shards, who compute per-user per-channel unread counts without scanning history, and who have a concrete answer for the reconnect storm when a gateway dies. Slack's real system uses Solr for message search, Envoy for terminating the socket fleet, and Enterprise Grid to stitch many workspaces into one organization.
readSnowflake System Design Interview: Building a Cloud Data Warehouse That Separates Storage from Compute
A cloud data warehouse has to serve fast analytical queries over enormous, mostly cold datasets while many teams load and read at once. Snowflake's answer is a three-layer split. Data sits once in object storage as immutable, compressed, columnar micro-partitions. Compute happens in virtual warehouses, which are elastic clusters you spin up, resize, and suspend independently, so an ingest job on one warehouse never fights a dashboard on another. A stateless cloud services layer holds all the brains: the optimizer, transaction manager, security, and the metadata catalog that records which micro-partitions make up each table version. Queries go fast not through indexes but through pruning, where per-column min and max statistics let the planner skip files that cannot match a predicate. Because files are immutable and tables are just a versioned list of files, you get ACID transactions with snapshot isolation, time travel to any point in a retention window, and zero-copy clones that duplicate a table by copying metadata rather than bytes. The design's core bet is that separating storage from compute buys near-infinite elasticity and workload isolation, and that object storage plus smart metadata can replace the tightly coupled shared-nothing clusters that came before.
readSpotify System Design Interview: Streaming Audio, Discover Weekly, and Billions of Play Events
Spotify looks like a simple play button, but the interesting engineering sits underneath it. Audio is not generated on the fly the way video often is. Every track is pre-encoded into a handful of Ogg Vorbis bitrates, chunked, and pushed to a CDN so the client can start playback in a few hundred milliseconds and switch quality as the network changes. The catalog and metadata for tracks, albums, artists, and playlists need fast lookups and search across a huge corpus. Personalization is the other half of the product: collaborative filtering and content signals feed offline batch jobs that precompute recommendations like Discover Weekly, which are then served from low latency stores. Tying it all together is an event pipeline that captures every play, skip, and save. That pipeline feeds royalty accounting, analytics, and the recommendation models, so it has to be durable and ordered enough to trust with payments. The hard parts to talk about in an interview are audio delivery and caching, the recommendation pipeline that splits offline compute from online serving, and the event delivery backbone that Spotify famously moved from Kafka to Google Cloud Pub/Sub.
readStock Exchange System Design: The Order Matching Engine
A stock exchange is a low-latency deterministic matching system, not a CRUD app. Orders arrive over gateways, get validated and risk-checked, then flow into a single sequenced input stream that assigns each event a monotonic sequence number. A single-threaded matching engine consumes that stream and applies each order to an in-memory limit order book, which keeps resting orders sorted by price and, within a price level, by arrival time. Matching follows price-time priority: the best price trades first, and ties break by who got there earliest. Because every replica consumes the exact same ordered input and the engine is deterministic, all replicas compute byte-identical output, so recovery and hot standby become replay problems rather than distributed-consensus problems on the hot path. Durability comes from journaling the sequenced input to an append-only log before or in parallel with matching, in the style of the LMAX Disruptor. Fills and book changes fan out as a market data feed with periodic snapshots plus incremental deltas. The design goal is microsecond-scale, jitter-free matching with zero data loss and provable determinism.
readSwiggy System Design Interview: Live Order Tracking
Designing Swiggy means solving three coupled problems at once: serviceability (which restaurants can even reach this customer), dispatch (which delivery partner picks up which order, often batched), and a three-party order state machine that survives a restaurant rejecting an order, a partner going offline mid-trip, or a payment webhook arriving late. The hard part is that almost all of the load lands in two short meal peaks, so the system is sized for 4-5x its average and idle the rest of the day.
readTelegram System Design Interview: Cloud Messaging, Multi-Device Sync, and Million-Subscriber Channels
Telegram is a cloud-first messenger. Cloud chats live server-side, encrypted at rest but readable by Telegram, which is what lets a brand new phone log in and instantly see full history, search, and media. This is the deliberate split from WhatsApp, which keeps the source of truth on your phone. The account is pinned to a home data center chosen at registration, and all of that user's cloud data lives there. Clients hold a persistent MTProto session and receive updates in real time. When a client reconnects after being offline, it does not replay every event. It compares its local sequence counters (pts, qts, seq) against the server and calls getDifference or getChannelDifference to fetch only the delta. Groups scale to 200,000 members and broadcast channels are effectively unlimited, so the design has to handle both tight 1:1 delivery and massive one-to-many fanout. End-to-end encryption exists only in Secret Chats, which are bound to a single device pair and never touch the cloud.
readTicketmaster System Design Interview: Selling Scarce Seats Without Double-Booking
A ticketing platform looks simple until one hot event goes on sale and a hundred thousand people fight over forty thousand seats in the same sixty seconds. The core requirement is that a given seat is sold to exactly one buyer, ever, even under massive concurrency, while the site stays up for everyone else. The design has three load-bearing pieces. First, a virtual waiting room that holds and paces arrivals so the booking backend only ever sees traffic it can handle. Second, a reservation model where selecting a seat places a short temporary hold that auto-releases if payment does not complete, so abandoned carts do not lock inventory forever. Third, an idempotent, serialized commit path where the transition from held to sold happens under a lock or a conditional write that a competing request cannot win twice. Around that sit the seat map, the payment integration, and a reconciliation loop that cleans up expired holds. Get the waiting room, the hold expiry, and the atomic sell right, and the rest is standard web engineering.
readTikTok System Design Interview: The For You Feed and Its Real-Time Recommender
The defining challenge of TikTok is the For You recommendation feed, not the video plumbing. A user opens the app with no explicit query and expects an endless stream of clips tuned to their taste, refreshed as their taste shifts inside a single session. The system answers this with a two-stage recommender. Candidate generation narrows hundreds of millions of videos down to a few hundred using cheap retrieval models and embedding lookups, then a heavier ranking model scores those candidates on many objectives at once, watch time, replay, like, share, comment, and follow probability. What makes the recommendations feel uncanny is freshness. ByteDance's Monolith training system updates the model online from live interaction streams rather than in nightly batches, so a signal from a video you watched a minute ago can influence what you see next. Around that core sits a conventional but very large video platform: an upload and transcoding pipeline that fans one master file into many bitrate and resolution renditions, object storage for the media, a CDN that pushes clips to edge caches near the viewer, and a client that aggressively prefetches the next few videos so the feed feels instant when you swipe.
read