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
77 posts · page 1 of 4
- Interview
API Design System Design Interview: Designing a REST, GraphQL, or gRPC API That Stays Backward Compatible, Idempotent, and Observable at Scale
API design is the practice of defining the contract between a service and its callers: the resources it exposes, the operations allowed on them, the shape of requests and responses, the error format, and the rules for authentication, versioning, and evolution. The three dominant styles are REST over HTTP (resource-oriented, cacheable, ubiquitous), GraphQL (a single endpoint with a typed query language that lets clients ask for exactly the fields they need), and gRPC (contract-first binary RPC over HTTP/2, fast and strongly typed, ideal for internal service-to-service calls). Most of the hard problems are the same regardless of style. You have to model resources and name them consistently, choose HTTP methods and status codes that mean what they say, decide how to version without breaking existing clients, paginate large collections without offset drift, make write operations idempotent so retries are safe, return machine-readable errors in a standard format such as RFC 7807 problem+json, authenticate and authorize callers, and defend the service with rate limits and quotas. Good API design leans hard toward backward compatibility, predictability, and least surprise, because the cost of a breaking change is paid by every integrator at once and cannot be undone unilaterally.
Read - Interview
DynamoDB System Design Interview: Designing a Distributed Key-Value Store That Serves Millions of Requests per Second at Single-Digit-Millisecond Latency
DynamoDB is a managed distributed key-value and document store descended from the 2007 Amazon Dynamo paper. You address every item by a primary key, and the system hashes that key to decide which partition, and therefore which set of storage nodes, owns the item. Data is partitioned by consistent hashing and replicated to a small number of nodes (typically three) across separate availability zones, so a single node or even a whole zone can fail without losing data or availability. The original Dynamo was fully leaderless and used vector clocks with application-side conflict resolution, but production DynamoDB moved to a per-partition leader with quorum-style replication and a write-ahead log, which is simpler for developers to reason about. Reads come in two flavors: eventually consistent (cheap, may be slightly stale) and strongly consistent (routed to the leader replica). The hard design themes are all trade-offs: how you pick a partition key so load spreads evenly instead of creating a hot partition, how the system reshares and moves data online as tables grow, how secondary indexes are kept up to date asynchronously, and how global tables give you multi-region writes at the cost of last-writer-wins conflict resolution. DynamoDB leans toward availability and predictable latency over rich query power and strong global consistency.
Read - Interview
Machine Learning System Design Interview: A Framework for Framing the Problem, Choosing Metrics, Building the Data and Feature Pipeline, and Serving Models in Production
Machine learning system design is a distinct interview format from classic system design. You are still expected to talk about services, storage, and scale, but the spine of the answer is the ML lifecycle: frame the problem, define metrics, get and label data, engineer features, pick a model, train it, evaluate it offline, ship it behind an A/B test, serve it within a latency budget, and monitor it for decay. A strong candidate starts by clarifying the business goal and deciding whether machine learning is even the right tool, since a rules-based or heuristic baseline is often the honest first answer. Then they translate the business goal into a concrete ML objective and separate the offline metric they train against from the online metric the business actually cares about, because those two rarely move together perfectly. The data section is where interviews are won or lost: where labels come from, how to avoid leakage, how to handle class imbalance, and how to prevent the train-serve skew that happens when features are computed one way in the training pipeline and a different way at serving time. That last problem is exactly what a feature store exists to solve. For the model itself, the disciplined move is to establish a simple baseline before reaching for anything complex, and for recommendation, search, and feed ranking (the most common ML design prompt) to use the two-stage candidate-generation-plus-ranking pattern that narrows millions of items down to a few hundred cheaply, then scores those precisely. Offline evaluation tells you whether a model is promising; only an online A/B test tells you whether it actually helps. Serving splits into batch (precompute predictions on a schedule) and online (compute on request), each with different latency and freshness trade-offs. Finally, the system needs monitoring for data drift and model decay, because an ML system that is not watched will silently get worse. The candidates who stand out are the ones who treat the model as the easy part and the platform around it (feature stores, low-latency serving, drift monitoring, retraining) as the hard part, because in production that is exactly where the difficulty and the value live.
Read - Interview
Time-Series Database System Design Interview: Designing a TSDB for Massive Append-Heavy Writes, High-Cardinality Metrics, and Fast Range Aggregations at Scale
A time-series database (TSDB) is a store optimized for data that is a sequence of timestamped values, such as CPU usage, request latency, sensor readings, or stock prices. Instead of thinking in rows and joins, it thinks in series: a metric name plus a set of key-value tags (labels) uniquely identifies one series, and each series is an ordered stream of (timestamp, value) points. Writes are append-heavy and mostly in timestamp order, reads are heavily skewed toward recent data, and queries are dominated by range scans and time-bucketed aggregations rather than point lookups. This workload breaks the assumptions of a general-purpose relational row store, so a TSDB makes different choices: it stores points columnar and per-series so that a scan touches only the columns and time ranges it needs, it compresses hard using delta-of-delta encoding on timestamps and XOR (Gorilla-style) encoding on floats to get roughly an order of magnitude reduction, and it partitions data by time so old data can be dropped or downsampled in bulk. Ingestion typically flows through a write-ahead log for durability and an in-memory head block for recent points, which is periodically flushed to immutable on-disk blocks. The central failure mode is cardinality: because every unique tag combination is a new series, a single high-cardinality label (a user id, a request id, a container id that churns) can explode the series count and blow up memory and index size. Retention and downsampling (raw to 1-minute to 1-hour rollups) keep long-term storage affordable, and the query engine adds time-series-native functions like rate, percentiles, and group-by-time. TSDBs lean toward cheap high-volume ingestion and fast recent-range queries, and away from arbitrary updates, cross-series joins, and unbounded cardinality.
Read - Interview
Design an AI Agent: Agentic System Design Interview
Wire a model to a few tools and you have something that looks like an agent; run it on a real task and the loop is where every hard problem surfaces. The model does not execute anything itself; it emits a request to call a tool, an orchestrator runs the tool, and the result is fed back for the next decision, over and over. The first thing that bites is reliability, because a chain of steps multiplies its per-step error rate, so the design has to add verification, retries, and bounded scope to stop a long task from almost certainly failing. The second is state, because an agent run is long enough to outlive the process running it, which turns it into a durable-execution problem closer to a workflow engine than to a web request: you record each step so a crash resumes instead of restarting. The third is memory, since the growing transcript is both the agent's working memory and its biggest cost, so you decide what to keep in the context window, what to push to a store and retrieve later, and what to summarize. The fourth is safety, and it is sharper than in a plain chatbot because the agent can act: a tool can send money or delete a file, and the untrusted text a tool returns can carry a prompt injection that hijacks the next decision, so tools run with least privilege and irreversible actions wait for a human. Cost ceilings, loop detection, parallel tool calls, and trajectory-level evaluation ride on top of all of it. Get the control loop and its guardrails right and the agent ships; get them wrong and no starting prompt will save it.
Read - Interview
Design ChatGPT: LLM Serving System Design Interview
Designing ChatGPT looks like designing a chat app until you notice the model is stateless and the GPU is the entire problem. Every turn resends the whole conversation, so the model reprocesses the full history to produce the next reply, and the cost of a conversation grows as it gets longer. Inference itself splits into two phases with opposite bottlenecks: prefill reads the prompt in parallel and saturates compute, while decode emits one token at a time and is limited by memory bandwidth, because each token has to re-read the model weights. That asymmetry drives nearly every decision. The KV cache that makes decode affordable is also what fills the GPU, so PagedAttention borrows virtual-memory paging to stop fragmentation from wasting most of the card, and continuous batching swaps finished sequences out at each iteration instead of waiting for the slowest one. Prefix caching turns a shared system prompt and a repeated conversation history into a cache hit rather than recomputation. Speculative decoding exploits the fact that verifying several tokens costs about the same as generating one. Then the product layer adds its own constraints: streaming so the answer starts before it is finished, moderation on both the input and the streaming output, token-based quotas rather than request-based ones, and routing that treats a GPU holding long conversations as full even when its request count looks low. The chat CRUD is a weekend project. The interview is about GPU memory, batching, and the latency budget.
Read - Interview
RAG System Design Interview: Retrieval-Augmented Generation from Chunking to Grounded Answers
Retrieval-augmented generation sounds simple, look up relevant text and paste it into an LLM prompt, but nearly every hard decision is hidden in that sentence. You have to split documents into chunks (how big, how much overlap, split on what boundary), embed them with a model you must then use identically at query time, and store the vectors in an index whose parameters trade recall against latency. At query time you decide between pure vector search and a hybrid of dense plus keyword search, whether to rerank the survivors with a slower cross-encoder, and how to fit the best chunks into a fixed token budget without burying the answer in the middle. Then you owe the user a grounded answer: the model must respond from the retrieved context and cite it, not hallucinate, which pushes you into prompt design, guardrails, and evaluation. On top of that sit the operational realities, keeping the index fresh as documents change, re-embedding the whole corpus when you switch models, filtering retrieval by tenant and permissions, and measuring retrieval quality and faithfulness rather than guessing. A strong answer treats the LLM call as the easy part and spends its time on chunking, retrieval quality, grounding, freshness, and cost.
Read - Interview
Ad Click Aggregator System Design Interview: Counting a Firehose Without Double-Charging Advertisers
An ad click aggregator ingests a massive stream of click and impression events, groups them into per ad, per time bucket counts, and serves two audiences from the same data: advertisers watching a near real time dashboard and a billing system that needs numbers it can defend. The core of the design is a durable log (Kafka) that absorbs the firehose and partitions events by ad id, a stream processor (Flink or Spark Structured Streaming) that runs windowed aggregation over event time, and an OLAP store (Druid, Pinot, or ClickHouse) that holds pre aggregated rollups and answers dashboard queries in well under a second. The hard parts are all about correctness under failure. Events arrive out of order and late, so you need watermarks and a grace period to decide when a minute is done. A click must be counted exactly once, so every event carries a stable id and gets deduplicated. A viral ad creates a hot partition that one consumer cannot keep up with. And because streaming counts can drift, most real systems keep a batch reconciliation path (or a replayable single stream) that produces the authoritative billing number a few hours later. The interview is really a tour of stream processing done under a billing constraint.
Read - Interview
Airbnb System Design Interview: Search, Availability, and the Race to Book the Same Listing
Airbnb is a two sided marketplace where hosts list homes and guests search, book, and pay. A guest types a place and a date range, and the system filters millions of listings by location, dates, price, guest count, and amenities, then ranks them with personalization, all in a couple hundred milliseconds. The genuinely hard subsystem is the booking write path: two guests can try to reserve the same listing for overlapping dates at the same instant, and the design must let exactly one of them win. That means a strongly consistent reservation store, usually a relational database sharded by listing, with row level locking or optimistic concurrency on the calendar, plus short lived holds during checkout. Search runs off a separate denormalized index such as Elasticsearch that is updated asynchronously from booking and calendar events, so search is eventually consistent by design while reservations are not. Payments split a guest charge from a delayed host payout and hold funds until after check in, which forces careful idempotency so a retried request never charges twice. The whole thing is a study in choosing where to pay for strong consistency and where eventual consistency is fine.
Read - Interview
Amazon S3 System Design Interview: Building Object Storage with Eleven Nines of Durability
Object storage exposes a dead simple contract: PUT an object under a key in a bucket, GET it back byte for byte, and never lose it. Underneath, that contract hides two genuinely hard systems. The first is the durability engine that takes each object, splits it into shards using Reed-Solomon erasure coding, and scatters those shards across many disks, racks, and availability zones so that no correlated failure can destroy more shards than the parity can rebuild, all while background scrubbers continuously read, verify checksums, and repair. The second is the metadata index that maps a key to the physical location of its shards, which must stay fast and consistent while holding entries for trillions of keys and absorbing request storms concentrated on a few hot prefixes. On top of those sit a stateless front-end router fleet, a chunked data path with multipart upload for large objects and range reads for partial GETs, and a lifecycle engine that migrates cold data into cheaper tiers. Since 2020 S3 has also offered strong read-after-write consistency, so a read that follows a successful write always sees the latest bytes. The design lesson is that availability comes from stateless replaceable front ends, and durability comes from spreading redundant coded data as widely as possible and never trusting a disk to tell you the truth about itself.
Read - Interview
Apache Kafka System Design Interview: Building a Distributed Message Queue on a Commit Log
Kafka is a distributed, partitioned, replicated commit log dressed up as a messaging system. A topic is split into partitions, and each partition is an append-only, totally ordered sequence of records addressed by a monotonically increasing offset. Producers append to the tail, consumers read forward at their own pace and track their own offset, and the same records can be re-read by many independent consumer groups because reading does not destroy the message. Ordering is guaranteed only within a partition, which is the price you pay for horizontal scale. Durability comes from replicating each partition to several brokers, with one leader taking all reads and writes and followers pulling to stay in sync. The in-sync replica set plus the acks setting lets you dial the tradeoff between latency and how many failures you can survive without losing an acknowledged write. The whole thing is fast because it leans on sequential disk I/O, the OS page cache, and zero-copy transfer rather than clever in-memory structures. Coordination that used to live in ZooKeeper now lives inside Kafka itself through the KRaft metadata quorum.
Read - Interview
API Gateway System Design Interview: Building the Single Front Door for Hundreds of Microservices
An API gateway is the single entry point that sits between external clients and a fleet of internal microservices. It terminates TLS, authenticates and authorizes each request, applies rate limits and quotas, routes to the correct upstream based on path or host or headers, and often transforms or aggregates responses before returning them. The hard part is that it is on the critical path for every request, so it must be fast, non-blocking, and horizontally scalable without becoming a single point of failure. Good designs treat the gateway as a thin, stateless, policy-enforcing proxy built around a chain of composable filters or plugins, with heavy work (business logic, data ownership) pushed back into the services. The interview is really about where responsibility belongs: what the gateway should own versus what it must never own. Candidates who put too much logic in the gateway rebuild a distributed monolith with a new name. The reference implementations to reason from are Netflix Zuul 2, Kong, Envoy, and AWS API Gateway, each of which models the request lifecycle as an ordered set of pluggable stages.
Read - Interview
BookMyShow System Design: Seat Booking Concurrency
A seat-level ticketing system where the hard part isn't scale, it's correctness under contention: 50,000 people clicking the same seat at the same millisecond, and exactly one of them must win. The design centers on a temporary seat-hold lock (Redis, ~10 min TTL, acquired with an atomic Lua compare-and-set), a virtual waiting room that gates the herd before it ever touches the booking service, and a payment saga that keeps the seat held until money clears, then either confirms the booking or releases the seat. Reads (seat maps, show listings) are massively cached and scale horizontally; writes (the actual booking) are funneled through a narrow, strongly-consistent path.
Read - Interview
Code Deployment System Design Interview: Shipping a Commit to 100,000 Servers Safely
A code deployment system takes a commit and carries it all the way to production: it builds the code, runs tests, produces an immutable artifact, stores that artifact, distributes it to every target host, and then flips traffic over in a controlled way. The design splits cleanly into a control plane that decides what should run where, and a data plane that actually moves bytes and swaps processes on each machine. The interesting engineering lives in two places. First, distribution: pushing a large artifact to tens of thousands of hosts from a central store saturates the origin, so real systems use peer to peer swarms or a tree of regional caches so that hosts pull from each other. Second, safety: you never flip all hosts at once, you use rolling, blue-green, or canary strategies with automated health checks and metric comparison so a bad build is caught on a small blast radius and rolled back fast. Everything hinges on immutable, versioned artifacts and a deployment state machine that can always answer what version is on which host and can drive it back to a known good version.
Read - Interview
CRED System Design Interview: Bill Payments and Rewards at Scale
Designing CRED is a fintech problem with three distinctive parts. First, membership is gated: a user can only join if their credit score clears a threshold, which is checked at onboarding against credit bureaus, so access control is part of the design rather than an afterthought. Second, the core action is paying a credit-card bill, which is an orchestrated money movement that CRED runs through a central order management system built on state machines and events. Third, the load is cyclical, concentrated around monthly billing due dates. This walkthrough centers on the order management system that CRED has published, the gated onboarding, and how the platform handles the monthly spike, and is honest about which payment and reconciliation details are the standard fintech pattern rather than CRED-published.
Read - Interview
Databricks System Design Interview: Building a Lakehouse with ACID on Object Storage
Databricks is a lakehouse: one system that stores data in cheap open-format files on object storage, then layers warehouse guarantees on top so you get ACID transactions, schema, and fast SQL without copying data into a separate warehouse. The center of the design is Delta Lake, which turns a folder of Parquet files into a real table by keeping an ordered transaction log next to the data. Every write appends a JSON commit that lists which files were added and removed, so a reader reconstructs an exact table snapshot by replaying the log. Concurrency is handled optimistically: writers assume conflicts are rare, do their work, and only check for a collision at commit time. Storage and compute are fully separated, so elastic Spark clusters spin up against the same files and scale independently. Photon accelerates queries with vectorized C++ execution, data skipping prunes files using per-file statistics, and OPTIMIZE compacts small files. Unity Catalog sits above all of it for governance, permissions, and lineage. The medallion pattern, bronze to silver to gold, organizes raw ingestion through cleaned and aggregated tables.
Read - Interview
Delhivery System Design Interview: Logistics Network at Scale
Designing Delhivery is the logistics-network problem, which is different from the consumer apps. A parcel is picked up, moves through a hub-and-spoke network of sort centers and gateways, and is delivered to a doorstep, and the whole thing runs at the scale of e-commerce infrastructure for the country. The distinctive engineering, and what Delhivery has published, is address intelligence: Indian addresses are unstructured and often carry the wrong pin code, so Delhivery built machine learning that resolves a messy address to a precise location, which lets it route by geocode rather than by pin code. This walkthrough covers the network, the address-resolution system Delhivery published, tracking at scale, and peak handling, and is honest about which internals are the standard logistics pattern.
Read - Interview
Design Amazon: System Design Interview Guide
Designing Amazon means designing an e-commerce stack from catalog and search through cart, checkout, inventory, payment, and fulfillment routing. It is one of the broadest system design problems because every step is a real subsystem with its own constraints. The hardest piece is keeping inventory consistent across 175 warehouses while serving sub-second search.
Read - Interview
Design Instagram: System Design Interview Guide
Designing Instagram combines photo upload pipelines, feed generation (similar to Twitter), Stories (a separate ephemeral feed), Direct Messages, and a heavy media CDN. The hardest piece is generating a personalized feed that mixes friends, followed accounts, and Reels recommendations in 200 milliseconds.
Read - Interview
Design Netflix: System Design Interview Guide
Designing Netflix forces you to think about video encoding pipelines, multi-CDN delivery with adaptive bitrate, a recommendation system that drives 80% of watched content, and a microservices architecture that has to stay up while half a million users press play in the same minute.
Read