<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[System Design Interview Roadmap]]></title><description><![CDATA[System Design Interview Roadmap - Step by step process that will make you comfortable, familiar & then expert. Preparing for a system design interview, probably at a FAANG-tier company, probably at L4–L6. That's exactly who this newsletter.]]></description><link>https://systemdr.systemdrd.com</link><image><url>https://substackcdn.com/image/fetch/$s_!_3Z_!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9fd573e1-44ca-4a06-be42-264560574975_500x500.png</url><title>System Design Interview Roadmap</title><link>https://systemdr.systemdrd.com</link></image><generator>Substack</generator><lastBuildDate>Sat, 01 Aug 2026 00:13:20 GMT</lastBuildDate><atom:link href="https://systemdr.systemdrd.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[SystemDR Inc]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[systemdr@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[systemdr@substack.com]]></itunes:email><itunes:name><![CDATA[System Design Roadmap]]></itunes:name></itunes:owner><itunes:author><![CDATA[System Design Roadmap]]></itunes:author><googleplay:owner><![CDATA[systemdr@substack.com]]></googleplay:owner><googleplay:email><![CDATA[systemdr@substack.com]]></googleplay:email><googleplay:author><![CDATA[System Design Roadmap]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Fine-Tuning Pipelines: Designing the Architecture for Custom Model Training]]></title><description><![CDATA[Introduction]]></description><link>https://systemdr.systemdrd.com/p/fine-tuning-pipelines-designing-the</link><guid isPermaLink="false">https://systemdr.systemdrd.com/p/fine-tuning-pipelines-designing-the</guid><dc:creator><![CDATA[System Design Roadmap]]></dc:creator><pubDate>Fri, 31 Jul 2026 08:30:20 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!NDQp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92b1ca2c-356a-4c2d-8e27-b11d494b999a_4950x3190.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2><blockquote><p>A base model is a hypothesis. A fine-tuned model is a product. The gap between those two things isn&#8217;t mathematical &#8212; it&#8217;s operational. Teams that treat fine-tuning as &#8220;run a script in a notebook&#8221; eventually hit a wall: reproducibility breaks, models regress silently, datasets drift, and nobody can explain which checkpoint shipped to production last Tuesday. Designing a fine-tuning pipeline is fundamentally a distributed systems problem wearing an ML hat.</p></blockquote><div><hr></div><h2>Core Concept: The Fine-Tuning Pipeline</h2><blockquote><p>Fine-tuning adapts a pre-trained foundation model to a specific task by continuing training on a curated domain dataset. The challenge isn&#8217;t the gradient math &#8212; it&#8217;s orchestrating the data, compute, validation, and versioning layers into a system that behaves correctly under failure, scales without bottlenecks, and produces artifacts you can actually trust.</p></blockquote><p>A production fine-tuning pipeline has five distinct stages that must be independently restartable and observable.</p><p><strong>Stage 1 &#8212; Data Ingestion &amp; Versioning</strong> Raw training data arrives from object storage (S3, GCS), annotation pipelines, or RLHF feedback systems. Before anything trains, every dataset version must be fingerprinted. Tools like DVC or Delta Lake provide immutable dataset snapshots. The failure pattern here: teams that skip versioning can&#8217;t answer &#8220;what data produced this model?&#8221; six months later &#8212; which kills audit trails and compliance.</p><p><strong>Stage 2 &#8212; Preprocessing &amp; Tokenization</strong> Raw text gets cleaned, filtered for quality (perplexity filtering, dedup via MinHash LSH), and tokenized into packed sequences. This stage runs on CPU-heavy workers (separate from GPU training nodes) and produces binary shard files. A common mistake: running tokenization inside the training loop wastes GPU cycles on CPU-bound work and creates non-deterministic throughput under variable data shapes.</p><p><strong>Stage 3 &#8212; Training Job Orchestration</strong> The training job itself is submitted to a job scheduler (Ray, Slurm, Kubernetes Job API) with explicit resource requests. Key decisions here: gradient checkpointing to trade compute for memory, mixed-precision (bf16/fp16) to reduce VRAM pressure, and gradient accumulation to simulate large batch sizes across limited hardware. For distributed runs, you choose between data parallelism (each node holds the full model), tensor parallelism (model sharded across nodes), or pipeline parallelism (model layers split across stages). Each has distinct failure modes &#8212; pipeline parallelism, for instance, introduces pipeline bubbles that reduce GPU utilization.</p><p><strong>Stage 4 &#8212; Checkpoint Management</strong> Training jobs die. GPU nodes preempt. Cloud spot instances evict. Checkpoints must be written to durable storage at regular intervals and the pipeline must resume from the latest valid checkpoint without human intervention. A subtlety: corrupted checkpoints (written during a crash) need detection logic. Write to a temp path, validate, then atomic rename.</p><p><strong>Stage 5 &#8212; Evaluation, Registry &amp; Promotion</strong> After training completes, the model runs against a frozen eval harness &#8212; benchmark tasks that don&#8217;t change between runs, covering both target task performance and regression tests for general capabilities. Models that pass thresholds get registered in a model registry (MLflow, Weights &amp; Biases Registry, or custom) with full lineage metadata: dataset version, hyperparameters, hardware config, eval scores. Promotion to staging or production requires explicit human approval or automated A/B gate logic.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NDQp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92b1ca2c-356a-4c2d-8e27-b11d494b999a_4950x3190.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NDQp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92b1ca2c-356a-4c2d-8e27-b11d494b999a_4950x3190.png 424w, https://substackcdn.com/image/fetch/$s_!NDQp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92b1ca2c-356a-4c2d-8e27-b11d494b999a_4950x3190.png 848w, https://substackcdn.com/image/fetch/$s_!NDQp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92b1ca2c-356a-4c2d-8e27-b11d494b999a_4950x3190.png 1272w, https://substackcdn.com/image/fetch/$s_!NDQp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92b1ca2c-356a-4c2d-8e27-b11d494b999a_4950x3190.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NDQp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92b1ca2c-356a-4c2d-8e27-b11d494b999a_4950x3190.png" width="1456" height="938" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/92b1ca2c-356a-4c2d-8e27-b11d494b999a_4950x3190.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:938,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2859002,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.substack.com/i/191362442?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92b1ca2c-356a-4c2d-8e27-b11d494b999a_4950x3190.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!NDQp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92b1ca2c-356a-4c2d-8e27-b11d494b999a_4950x3190.png 424w, https://substackcdn.com/image/fetch/$s_!NDQp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92b1ca2c-356a-4c2d-8e27-b11d494b999a_4950x3190.png 848w, https://substackcdn.com/image/fetch/$s_!NDQp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92b1ca2c-356a-4c2d-8e27-b11d494b999a_4950x3190.png 1272w, https://substackcdn.com/image/fetch/$s_!NDQp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92b1ca2c-356a-4c2d-8e27-b11d494b999a_4950x3190.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p>
      <p>
          <a href="https://systemdr.systemdrd.com/p/fine-tuning-pipelines-designing-the">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Design a Distributed Cache (Redis-style) — The Senior+ Walkthrough]]></title><description><![CDATA[This question is asked as a standalone (&#8221;design a distributed cache&#8221;) and as the deep-dive in almost every other system design question (&#8221;you mentioned adding a cache &#8212; walk me through how you&#8217;d build that&#8221;).]]></description><link>https://systemdr.systemdrd.com/p/design-a-distributed-cache-redis</link><guid isPermaLink="false">https://systemdr.systemdrd.com/p/design-a-distributed-cache-redis</guid><dc:creator><![CDATA[System Design Roadmap]]></dc:creator><pubDate>Tue, 28 Jul 2026 03:30:17 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!04tk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9c0dc013-8546-418f-84e7-a95f2f32a325_4500x2400.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote><p><span>This question is asked as a standalone (&#8221;design a distributed cache&#8221;) and as the deep-dive in almost every other system design question (&#8221;you mentioned adding a cache &#8212; walk me through how you&#8217;d build that&#8221;). It tests whether you understand cache eviction, consistent hashing, replication, and what happens when a cache node fails.</span></p></blockquote><h2><span>The Question</span></h2><p><span>&#8220;Design a distributed in-memory cache like Redis. Support GET and SET operations. The cache should be fast, scalable, and handle node failures gracefully.&#8221;</span></p><h2><span>Step 1 &#8212; Clarify</span></h2><p><strong><span>1. Capacity? </span></strong><span>Total data size to cache. This determines how many nodes you need. A single Redis instance handles ~10&#8211;25 GB of working memory effectively.</span></p><p><strong><span>2. Eviction policy? </span></strong><span>LRU (least recently used) is the most common. Also: LFU (least frequently used), FIFO, TTL-based expiry. State which one unless the interviewer specifies.</span></p><p><strong><span>3. Write policy? </span></strong><span>Write-through (update cache and DB simultaneously &#8212; strong consistency, higher write latency) vs write-around (bypass cache on writes, populate on read) vs write-back/write-behind (write to cache first, async persist to DB &#8212; lower latency, risk of data loss).</span></p><p><strong><span>4. Read policy? </span></strong><span>Cache-aside (application checks cache first, populates on miss) vs read-through (cache automatically fetches from DB on miss). Cache-aside is the default; read-through requires the cache to know the DB schema.</span></p><p><strong><span>5. Replication? </span></strong><span>Single leader + replicas (Redis Sentinel model) or leaderless (Redis Cluster model)?</span></p><h2><span>Step 2 &#8212; Estimate</span></h2><p><span>- 10 TB of data to cache across the cluster</span></p><p><span>- Target: &lt; 1ms p99 for GET/SET</span></p><p><span>- Each node: 25 GB RAM &#8594; 400 nodes for 10 TB</span></p><p><span>- Throughput: 500K ops/sec per node &#8594; 200M ops/sec cluster capacity - Network: 1 Gbps per node, each GET returns avg 1 KB &#8594; 1M GETs/sec per node on bandwidth alone</span></p><p><span>The key insight: at 400 nodes, the routing layer (consistent hashing) must direct each request to the right node in &lt; 0.1ms overhead, leaving &lt; 0.9ms for the actual lookup.</span></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe&quot;,&quot;text&quot;:&quot;Get Access to GitHub Repo&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://systemdr.systemdrd.com/subscribe"><span>Get Access to GitHub Repo</span></a></p><h2><span>Step 3 &#8212; Core Data Structures</span></h2><p><strong><span>Hash table with LRU eviction:</span></strong></p><p><span>The cache is essentially a hash map + a doubly-linked list for LRU tracking.</span></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!VTns!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F112f9628-5a47-4ded-a1de-8ea99500968a_4500x1800.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VTns!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F112f9628-5a47-4ded-a1de-8ea99500968a_4500x1800.png 424w, https://substackcdn.com/image/fetch/$s_!VTns!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F112f9628-5a47-4ded-a1de-8ea99500968a_4500x1800.png 848w, https://substackcdn.com/image/fetch/$s_!VTns!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F112f9628-5a47-4ded-a1de-8ea99500968a_4500x1800.png 1272w, https://substackcdn.com/image/fetch/$s_!VTns!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F112f9628-5a47-4ded-a1de-8ea99500968a_4500x1800.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!VTns!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F112f9628-5a47-4ded-a1de-8ea99500968a_4500x1800.png" width="716" height="286.2032967032967" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/112f9628-5a47-4ded-a1de-8ea99500968a_4500x1800.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:582,&quot;width&quot;:1456,&quot;resizeWidth&quot;:716,&quot;bytes&quot;:423160,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.systemdrd.com/i/207242844?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F112f9628-5a47-4ded-a1de-8ea99500968a_4500x1800.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!VTns!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F112f9628-5a47-4ded-a1de-8ea99500968a_4500x1800.png 424w, https://substackcdn.com/image/fetch/$s_!VTns!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F112f9628-5a47-4ded-a1de-8ea99500968a_4500x1800.png 848w, https://substackcdn.com/image/fetch/$s_!VTns!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F112f9628-5a47-4ded-a1de-8ea99500968a_4500x1800.png 1272w, https://substackcdn.com/image/fetch/$s_!VTns!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F112f9628-5a47-4ded-a1de-8ea99500968a_4500x1800.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><span>- Hash map: key &#8594; (value, pointer to LRU list node) &#8212; O(1) GET</span></p><p><span>- Doubly-linked list: most-recently-used at head, least-recently-used at tail - On GET: move the accessed node to the head of the list &#8212; O(1)</span></p><p><span>- On SET: add to head. If capacity exceeded: remove from tail (evict LRU) &#8212; O(1) - On eviction: remove from hash map and list simultaneously &#8212; O(1)</span></p><p><span>This O(1) for both GET and eviction is the data structure insight interviewers test. A naive LRU using a sorted list would be O(N) on every access.</span></p><h2><span>Step 4 &#8212; Consistent Hashing (the probe)</span></h2><p><span>With 400 nodes, how do you decide which node stores key K?</span></p><p><strong><span>Naive modulo hashing: </span></strong><span>node = hash(key) % N. Simple. But when you add or remove a node (N changes), nearly every key remaps to a different node. A node failure or scale event causes a cache stampede &#8212; every miss hits the DB simultaneously.</span></p><p><strong><span>Consistent hashing:</span></strong></p><p><span>Place nodes on a circular ring (0 to 2&#179;&#178; - 1). Each node is assigned a position by hashing its identifier. To find the node for key K: hash K, find the nearest node clockwise on the ring.</span></p><div class="callout-block" data-callout="true"><p><span>Preparing for a distributed systems interview?</span><br><span>&#8594;</span><a href="https://systemdrd.com/ebooks/sdcourse-distributed-systems-interview">Download the free Interview Pack</a><br><span>&#8594; </span><a href="https://systemdr.systemdrd.com/subscribe">Subscribe</a><span> now to access source code repository - 200 + coding lessons</span></p></div>
      <p>
          <a href="https://systemdr.systemdrd.com/p/design-a-distributed-cache-redis">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Sharding: The Decision You Get Wrong Every Time]]></title><description><![CDATA[&#8220;I&#8217;d shard by user ID.&#8221;]]></description><link>https://systemdr.systemdrd.com/p/sharding-the-decision-you-get-wrong</link><guid isPermaLink="false">https://systemdr.systemdrd.com/p/sharding-the-decision-you-get-wrong</guid><dc:creator><![CDATA[System Design Roadmap]]></dc:creator><pubDate>Sun, 26 Jul 2026 03:30:39 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Uo-I!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3755edca-b023-4bc6-aabe-93038180b872_4400x2860.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>&#8220;I&#8217;d shard by user ID.&#8221;</p><p>This sentence appears in roughly 60% of system design interview answers involving a database. Sometimes it&#8217;s correct. Often it isn&#8217;t. Almost always it&#8217;s stated without the reasoning that determines whether it&#8217;s right or wrong.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">System Design Interview Roadmap is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>The reasoning is everything. The partition key isn&#8217;t a preference &#8212; it&#8217;s a consequence of your read pattern.</p><p><strong>The rule</strong></p><p>Partition on the dimension you query by most frequently.</p><p>If the most common query is &#8220;give me all messages for user X&#8221; &#8212; partition by user_id. Every message for user X is on the same shard. One network hop.</p><p>If the most common query is &#8220;give me all messages in conversation C&#8221; &#8212; partition by conversation_id. Every message in conversation C is on the same shard.</p><p>Partition by sender_id in a messaging system where reads are by recipient? Every delivery requires querying every shard. You&#8217;ve distributed your data in a way that makes your hot read path maximally expensive.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Uo-I!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3755edca-b023-4bc6-aabe-93038180b872_4400x2860.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Uo-I!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3755edca-b023-4bc6-aabe-93038180b872_4400x2860.png 424w, https://substackcdn.com/image/fetch/$s_!Uo-I!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3755edca-b023-4bc6-aabe-93038180b872_4400x2860.png 848w, https://substackcdn.com/image/fetch/$s_!Uo-I!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3755edca-b023-4bc6-aabe-93038180b872_4400x2860.png 1272w, https://substackcdn.com/image/fetch/$s_!Uo-I!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3755edca-b023-4bc6-aabe-93038180b872_4400x2860.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Uo-I!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3755edca-b023-4bc6-aabe-93038180b872_4400x2860.png" width="1456" height="946" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3755edca-b023-4bc6-aabe-93038180b872_4400x2860.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:946,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:838901,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.systemdrd.com/i/198938251?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3755edca-b023-4bc6-aabe-93038180b872_4400x2860.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Uo-I!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3755edca-b023-4bc6-aabe-93038180b872_4400x2860.png 424w, https://substackcdn.com/image/fetch/$s_!Uo-I!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3755edca-b023-4bc6-aabe-93038180b872_4400x2860.png 848w, https://substackcdn.com/image/fetch/$s_!Uo-I!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3755edca-b023-4bc6-aabe-93038180b872_4400x2860.png 1272w, https://substackcdn.com/image/fetch/$s_!Uo-I!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3755edca-b023-4bc6-aabe-93038180b872_4400x2860.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>How to get it right</strong></p><p>Before naming a partition key, write down the two or three most frequent queries the system needs to serve. Then choose the partition key that makes those queries hit one shard.</p><p>For a payment system: the hot query is &#8220;give me all transactions for account X.&#8221; Partition by account_id.</p><p>For a ride-sharing system: the hot query is &#8220;give me all active drivers within 5km of this point.&#8221; Geohashing is the partition key &#8212; drivers in the same geohash cell land on the same shard.</p><p>For a social feed: the hot query is &#8220;give me all posts for user X&#8217;s followers, sorted by time.&#8221; Partition by user_id &#8212; each user&#8217;s feed is co-located.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe&quot;,&quot;text&quot;:&quot;Subscribe for Question Walkthrough&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://systemdr.systemdrd.com/subscribe"><span>Subscribe for Question Walkthrough</span></a></p><p><strong>The celebrity problem</strong></p><p>Even correct partition key choices have a failure mode: hot partitions.</p><p>If you partition a social graph by user_id and one of your users is a celebrity with 100 million followers, every follow/unfollow event writes to one shard. Every timeline read for those 100 million followers potentially reads from one shard. That shard is getting 100&#215; the load of any other.</p><p>The fix depends on what&#8217;s hot. For write-heavy celebrities: scatter their data across multiple shards using a compound key (user_id + bucket_id), then merge at read time. For read-heavy content: replicate it across shards so reads can be served locally.</p><p>The L5 answer names the hot partition problem. The L6 answer names the specific fix and the conditions under which you&#8217;d apply it.</p><p><strong>The mechanical keys worth memorizing</strong></p><p>Some partition key decisions are standard enough that deviating from them signals a mistake:</p><p>Messages: by recipient_id (the hot read is &#8220;messages for user X&#8221;)</p><p>Notifications: by user_id (same reason)</p><p>Ride locations: by geohash (the hot read is proximity query)</p><p>Payment transactions: by account_id (the hot read is account history)</p><p>Web sessions: by session_id (the hot read is session lookup by ID)</p><p>Analytics events: by event_time or by (user_id, date) if per-user queries dominate</p><p>When you name a partition key in an interview, the follow-up is almost always: &#8220;what&#8217;s the failure mode?&#8221; The correct answer is almost always: &#8220;hot partitions when the distribution is uneven &#8212; here&#8217;s how I&#8217;d detect and address them.&#8221;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!DPH-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdd9cc10-03e3-46c7-9039-a93c26cc156c_4675x3410.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!DPH-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdd9cc10-03e3-46c7-9039-a93c26cc156c_4675x3410.png 424w, https://substackcdn.com/image/fetch/$s_!DPH-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdd9cc10-03e3-46c7-9039-a93c26cc156c_4675x3410.png 848w, https://substackcdn.com/image/fetch/$s_!DPH-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdd9cc10-03e3-46c7-9039-a93c26cc156c_4675x3410.png 1272w, https://substackcdn.com/image/fetch/$s_!DPH-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdd9cc10-03e3-46c7-9039-a93c26cc156c_4675x3410.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!DPH-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdd9cc10-03e3-46c7-9039-a93c26cc156c_4675x3410.png" width="1456" height="1062" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bdd9cc10-03e3-46c7-9039-a93c26cc156c_4675x3410.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1062,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1045435,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.systemdrd.com/i/198938251?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdd9cc10-03e3-46c7-9039-a93c26cc156c_4675x3410.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!DPH-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdd9cc10-03e3-46c7-9039-a93c26cc156c_4675x3410.png 424w, https://substackcdn.com/image/fetch/$s_!DPH-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdd9cc10-03e3-46c7-9039-a93c26cc156c_4675x3410.png 848w, https://substackcdn.com/image/fetch/$s_!DPH-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdd9cc10-03e3-46c7-9039-a93c26cc156c_4675x3410.png 1272w, https://substackcdn.com/image/fetch/$s_!DPH-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdd9cc10-03e3-46c7-9039-a93c26cc156c_4675x3410.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>What &#8220;sharding&#8221; actually is</strong></p><blockquote><p>One last thing worth naming explicitly: sharding and partitioning are often used interchangeably in interviews, but they mean slightly different things. Partitioning is dividing data logically. Sharding is distributing those partitions across separate physical nodes. When interviewers ask &#8220;how would you shard the users table?&#8221; they mean both.</p></blockquote><blockquote><p>The answer format that works: state the partition key, explain why it fits the read pattern, name the hot partition risk, and describe the mitigation. Four sentences. Every sharding answer.</p></blockquote><div><hr></div><p><strong>CTA:</strong> The distributed cache walkthrough (paid post #10) goes deep on consistent hashing and the hot partition problem specifically &#8212; including the virtual nodes fix and the thundering herd mitigation when a shard fails. </p><p><br><strong>Interested in mastering this topic?</strong> </p><p>Unlock premium content with deeper explanations and real implementation patterns.</p><h2><strong>Subscription link</strong></h2><p><a href="https://systemdr.systemdrd.com/subscribe">https://systemdr.systemdrd.com/subscribe</a></p><p>&#8212;Sumedh</p><div class="callout-block" data-callout="true"><p>The Question Vault has all 52 walkthroughs organized by archetype &#8212; so you can see the pattern across questions, not just the surface answer.</p><p><strong><span>Access all 52 Questions </span><a href="https://systemdrd.com/ebooks/52-faang-questions-drillcards-cheatsheets/">here</a></strong></p></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">System Design Interview Roadmap is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Prompt Caching Strategies: Reducing Costs and Latency in AI Apps]]></title><description><![CDATA[Introduction]]></description><link>https://systemdr.systemdrd.com/p/prompt-caching-strategies-reducing</link><guid isPermaLink="false">https://systemdr.systemdrd.com/p/prompt-caching-strategies-reducing</guid><dc:creator><![CDATA[System Design Roadmap]]></dc:creator><pubDate>Fri, 24 Jul 2026 08:30:56 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!xejB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdefc2460-1cb5-4fe9-85df-90dc202a05cd_4950x3080.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1>Introduction</h1><blockquote><p>Every time your application sends a 10,000-token system prompt to an LLM, the model recomputes attention over every single token &#8212; even if that system prompt hasn&#8217;t changed in weeks. For a product doing 50,000 requests per day, you&#8217;re paying full price 50,000 times to process the same instructions. Prompt caching eliminates that waste by storing the computed internal state of repeated token sequences and reusing it on subsequent requests.</p></blockquote><div><hr></div><h2>How Transformer KV Caching Works</h2><blockquote><p>Before a transformer generates any output token, it processes your entire input through multiple attention layers. In each layer, every input token produces a <strong>Key</strong> and a <strong>Value</strong> vector &#8212; the KV pair. Attention then computes how much each token should attend to every other token by comparing queries against all keys and weighting the corresponding values. This operation is O(n&#178;) in sequence length.</p></blockquote><p>When you send the same prefix (e.g., a system prompt) across thousands of requests, you&#8217;re recomputing those same KV pairs from scratch each time. Prompt caching short-circuits this: after processing a token sequence, the provider stores the KV tensors for that prefix in high-bandwidth memory. On the next request with the identical prefix, the model skips recomputation and loads the cached KV state directly into the attention layers.</p><blockquote><p>The critical constraint: <strong>the cache is keyed on an exact token-level prefix match.</strong> If you insert a user-specific sentence at position 50 of a 2,000-token system prompt, you&#8217;ve broken the prefix and busted the cache for everything after position 50. Cached content must always appear before dynamic content.</p></blockquote><p><strong>Anthropic&#8217;s implementation</strong> (as of late 2024) uses <code>cache_control: {type: "ephemeral"}</code> markers at specific content boundaries. Cache TTL is 5 minutes, reset on each cache hit, with a minimum cacheable block of 1,024 tokens. Cache write costs 25% more than a standard input token; cache reads cost 10% of the standard price &#8212; so a prefix hit after the first write is 90% cheaper per token on that segment.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">System Design Interview Roadmap is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p><strong>Google&#8217;s Gemini context caching</strong> requires a minimum of 32,768 tokens and supports 1-hour TTLs with explicit expiry control. Their pricing model charges a per-hour storage fee for the cached context plus a reduced input price on cache hits &#8212; optimized for long-document workflows rather than high-frequency short exchanges.</p><p><strong>OpenAI&#8217;s automatic caching</strong> (as of late 2024) requires no explicit markers &#8212; the API silently reuses KV state for repeated prefixes longer than 1,024 tokens, with cache hits appearing in the usage metadata. The tradeoff: less control over what gets cached.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xejB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdefc2460-1cb5-4fe9-85df-90dc202a05cd_4950x3080.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xejB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdefc2460-1cb5-4fe9-85df-90dc202a05cd_4950x3080.png 424w, https://substackcdn.com/image/fetch/$s_!xejB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdefc2460-1cb5-4fe9-85df-90dc202a05cd_4950x3080.png 848w, https://substackcdn.com/image/fetch/$s_!xejB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdefc2460-1cb5-4fe9-85df-90dc202a05cd_4950x3080.png 1272w, https://substackcdn.com/image/fetch/$s_!xejB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdefc2460-1cb5-4fe9-85df-90dc202a05cd_4950x3080.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xejB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdefc2460-1cb5-4fe9-85df-90dc202a05cd_4950x3080.png" width="1456" height="906" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/defc2460-1cb5-4fe9-85df-90dc202a05cd_4950x3080.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:906,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2113089,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.substack.com/i/191362430?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdefc2460-1cb5-4fe9-85df-90dc202a05cd_4950x3080.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!xejB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdefc2460-1cb5-4fe9-85df-90dc202a05cd_4950x3080.png 424w, https://substackcdn.com/image/fetch/$s_!xejB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdefc2460-1cb5-4fe9-85df-90dc202a05cd_4950x3080.png 848w, https://substackcdn.com/image/fetch/$s_!xejB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdefc2460-1cb5-4fe9-85df-90dc202a05cd_4950x3080.png 1272w, https://substackcdn.com/image/fetch/$s_!xejB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdefc2460-1cb5-4fe9-85df-90dc202a05cd_4950x3080.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><h2>Critical Insights</h2><p><strong>Structure your prompts as prefix stacks.</strong> Place static content first: system instructions &#8594; static examples &#8594; document context &#8594; dynamic user content. This isn&#8217;t stylistic &#8212; it&#8217;s the only way the prefix invariant holds. Teams that put user names or session IDs early in system prompts destroy their cache hit rate entirely.</p><p><strong>Cache writes are not free.</strong> On Anthropic&#8217;s API, writing a new cache entry costs 1.25&#215; the normal input price. If your TTL is 5 minutes and traffic is sparse enough that entries expire before being hit twice, you&#8217;re paying a premium with no benefit. Caching pays off when expected hits &#215; (1 - 0.10) &gt; expected misses &#215; 0.25 &#8212; roughly when you expect more than one hit per write within the TTL window.</p><p><strong>Few-shot examples are the highest-ROI caching target.</strong> A carefully crafted 50-example few-shot block can run 3,000&#8211;8,000 tokens. It&#8217;s static, deterministic, and processed identically on every call. Caching it drops that segment&#8217;s cost by 90% with no design constraints.</p><p><strong>Document context caching changes RAG economics.</strong> Traditional RAG retrieves and injects 2,000&#8211;8,000 token chunks per query. With caching, you can inject a full 50,000-token document once, cache it, and run dozens of questions against it within the TTL &#8212; paying full price only on the first call. This is particularly effective for legal document Q&amp;A, code review assistants, and report analysis pipelines.</p><p><strong>Dynamic content length affects effective cache depth.</strong> If your user turn averages 200 tokens but your cached prefix is 4,000 tokens, 95% of input tokens are cached. If your average user turn is 3,000 tokens (e.g., pasting full code files), your effective cache fraction drops to 57%. Design your interface to keep dynamic content short and push static context into the cache.</p><p><strong>Cache cold starts hurt p99 latency.</strong> The first request after a cache miss processes all tokens from scratch &#8212; often 2&#8211;4&#215; slower than a cache hit. Under bursty traffic where cache entries expire during a quiet period, you&#8217;ll see latency spikes as entries are rewarmed. Build latency SLOs that account for this; don&#8217;t measure average latency alone.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!caYP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63fecf9d-51cd-4119-a88f-e47d7577ff70_4950x3300.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!caYP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63fecf9d-51cd-4119-a88f-e47d7577ff70_4950x3300.png 424w, https://substackcdn.com/image/fetch/$s_!caYP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63fecf9d-51cd-4119-a88f-e47d7577ff70_4950x3300.png 848w, https://substackcdn.com/image/fetch/$s_!caYP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63fecf9d-51cd-4119-a88f-e47d7577ff70_4950x3300.png 1272w, https://substackcdn.com/image/fetch/$s_!caYP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63fecf9d-51cd-4119-a88f-e47d7577ff70_4950x3300.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!caYP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63fecf9d-51cd-4119-a88f-e47d7577ff70_4950x3300.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/63fecf9d-51cd-4119-a88f-e47d7577ff70_4950x3300.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1998988,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.substack.com/i/191362430?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63fecf9d-51cd-4119-a88f-e47d7577ff70_4950x3300.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!caYP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63fecf9d-51cd-4119-a88f-e47d7577ff70_4950x3300.png 424w, https://substackcdn.com/image/fetch/$s_!caYP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63fecf9d-51cd-4119-a88f-e47d7577ff70_4950x3300.png 848w, https://substackcdn.com/image/fetch/$s_!caYP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63fecf9d-51cd-4119-a88f-e47d7577ff70_4950x3300.png 1272w, https://substackcdn.com/image/fetch/$s_!caYP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63fecf9d-51cd-4119-a88f-e47d7577ff70_4950x3300.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><h2>Real-World Examples</h2><p><strong>Cursor (AI code editor)</strong> caches the entire workspace context &#8212; open files, project structure, and coding conventions &#8212; for each session. Their reported cache hit rates exceed 80% for active sessions, with per-request costs reduced 3&#8211;5&#215; compared to naive injection. The architectural key: they keep file content structurally before the user&#8217;s active question, maintaining prefix integrity even as individual files change.</p><blockquote><p><strong>Notion AI</strong> uses document-level caching for their &#8220;Ask about this page&#8221; feature. A 20,000-word document gets cached once; all subsequent questions in that session hit the cache. They pad the document to 32,768 tokens when using Gemini to ensure eligibility. This reduced their per-query cost by roughly 60% on document-heavy workloads.</p></blockquote><p><strong>Harvey AI (legal)</strong> caches jurisdiction-specific prompt libraries &#8212; sometimes 40,000+ tokens of statutory references and case law summaries &#8212; as static prefix layers. Because legal workflows involve repetitive document review, a single cache write typically returns 15&#8211;30 hits before expiry.</p><div><hr></div><h2>Architectural Considerations</h2><blockquote><p>Prompt caching is invisible to your application&#8217;s logic but visible in cost and latency profiles. Build cache hit rate into your observability stack &#8212; most providers expose <code>cache_read_input_tokens</code> and <code>cache_creation_input_tokens</code> in usage metadata. Alert when hit rate drops below a threshold, since it signals a structural change in how prompts are being constructed.</p></blockquote><p>Caching interacts with streaming: cache hits reduce time-to-first-token noticeably, which improves perceived responsiveness even when total generation time is similar. Monitor TTFT separately from generation throughput.</p><p>Avoid caching highly user-specific content (PII, session tokens, per-user preferences) in the shared prefix layer &#8212; this creates both cache poisoning risk and privacy surface area. Keep personalization in the dynamic suffix.</p><div><hr></div><h2>Practical Takeaway</h2><h2><strong>GitHub Link</strong></h2><p><a href="https://github.com/sysdr/sdir/tree/main/Prompt_caching_strategies/prompt-caching-demo">https://github.com/sysdr/sdir/tree/main/Prompt_caching_strategies/prompt-caching-demo</a></p><p>Audit your current prompt structure before any other optimization. Separate it into: (1) static system instructions, (2) static few-shot examples, (3) static document context, (4) dynamic user content. Add <code>cache_control</code> markers at each static boundary. Measure cache hit rate for one week.</p><blockquote><p>For most production applications hitting the same model endpoint repeatedly, this single change reduces input token costs by 40&#8211;70% with no quality impact.</p></blockquote><p>Run <code>bash setup.sh</code> to launch a local demo with a real Anthropic API backend. The dashboard sends identical system prompts with and without caching enabled, tracks cache hit/miss rates, measures latency distributions, and calculates live cost savings. Set your <code>ANTHROPIC_API_KEY</code> as an environment variable before running. Extend it by adding your own system prompt in <code>config/prompts.js</code> and watching how prompt structure (prefix vs. suffix placement) changes your cache hit rate in real time.</p><div><hr></div><h3><em>Youtube Demo Link:</em></h3><div id="youtube2-p_mec4ePEUQ" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;p_mec4ePEUQ&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/p_mec4ePEUQ?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">System Design Interview Roadmap is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Design Typeahead / Search Autocomplete — The Senior+ Walkthrough ]]></title><description><![CDATA[This is one of the most common system design interview questions across all company tiers, asked at Google, Amazon, Twitter, and virtually every product company.]]></description><link>https://systemdr.systemdrd.com/p/design-typeahead-search-autocomplete</link><guid isPermaLink="false">https://systemdr.systemdrd.com/p/design-typeahead-search-autocomplete</guid><dc:creator><![CDATA[System Design Roadmap]]></dc:creator><pubDate>Tue, 21 Jul 2026 03:31:18 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!H9At!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad79390c-d559-41d7-a8be-b9ade039d2a9_4500x2250.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><span>This is one of the most common system design interview questions across all company tiers, asked at Google, Amazon, Twitter, and virtually every product company. </span></p><p><span>The reason: it has a clear probe (the trie data structure and its distributed form), and it reveals whether candidates</span></p><p><span>understand read-heavy system optimization, pre-computation, and the latency constraints of real-time user interaction.</span></p><h3><span>The Question</span></h3><p><span>&#8220;Design the search autocomplete / typeahead system. As a user types in a search box, the system suggests the top 5&#8211;10 completions in real time.&#8221;</span></p><p><span>Variants: &#8220;Design Google search suggestions,&#8221; &#8220;Design Twitter&#8217;s search autocomplete,&#8221; &#8220;Design Amazon&#8217;s search bar.&#8221;</span></p><h3><span>Step 1 &#8212; Clarify</span></h3><p style="text-align: justify;"><strong><span>1. What goes in suggestions? </span></strong><span>Historical search queries (Google-style), titles in a product catalog (Amazon-style), or usernames/topics (Twitter-style)? The data source changes the indexing strategy significantly.</span></p><p><strong><span>2. How many queries is the system handling? </span></strong><span>Google processes ~100K searches/sec. For most interviews: 10M DAU &#215; 10 searches/day = 100M searches/day = ~1,200/sec average, 10K/sec peak.</span></p><p><strong><span>3. How fresh must suggestions be? </span></strong><span>Do new trending searches need to appear in suggestions within minutes, or is 24-hour staleness acceptable? Real-time freshness is much harder. Start by assuming daily updates &#8212; offer to discuss real-time as an extension.</span></p><p><strong><span>4. Personalized or global? </span></strong><span>Global suggestions (same results for all users) are vastly simpler. Personalized (based on your history) requires per-user ranking on top of the global index.</span></p><p><strong><span>5. Latency SLO? </span></strong><span>Suggestions must appear within 100ms of each keystroke to feel real-time. This is the hardest constraint in the system.</span></p><h3><span>Step 2 &#8212; Estimate</span></h3><p><span>- 10K search requests/sec at peak (one autocomplete request per keystroke) - Average query length: 20 characters &#8594; 20 requests per search session in the worst case</span></p><p><span>- Top-K queries to track: top 10 million unique queries globally</span></p><p><span>- Trie storage: each node is ~16 bytes (character + children pointers + metadata) &#8212; a trie of 10M queries averages ~50M nodes &#215; 16 bytes = 800 MB. </span><strong><span>Fits in memory on a single machine.</span></strong></p><p><span>- Response size: 5&#8211;10 query strings, avg 30 bytes each = 300 bytes per response</span></p><p><span>The 800 MB insight is critical. The entire suggestion index for most production systems fits in memory. This is what enables sub-millisecond lookups.</span></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe&quot;,&quot;text&quot;:&quot;Get Access to GitHub Repo&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://systemdr.systemdrd.com/subscribe"><span>Get Access to GitHub Repo</span></a></p><h3><span>Step 3 &#8212; Data Model and Core Data Structure</span></h3><p><span>The trie</span></p><p><span>A trie (prefix tree) is the natural structure for autocomplete. Each node represents a character. A path from root to a node spells a prefix. Each node stores the top-K completions for that prefix.</span></p><div class="callout-block" data-callout="true"><p><span>root</span></p><p><span>&#9492;&#9472;&#9472; &#8216;s&#8217;</span></p><p><span>&#9492;&#9472;&#9472; &#8216;e&#8217;</span></p><p><span>&#9492;&#9472;&#9472; &#8216;a&#8217;</span></p><p><span>&#9500;&#9472;&#9472; &#8216;r&#8217; &#8594; [&#8221;search engine&#8221;, &#8220;search bar&#8221;, &#8220;sear...&#8221;] &#8592; top-5 stored here</span></p><p><span>&#9492;&#9472;&#9472; &#8216;s&#8217; &#8594; [&#8221;season&#8221;, &#8220;seasoning&#8221;, ...]</span></p></div><p><strong><span>The key design choice: </span></strong><span>Pre-compute and cache the top-K results at every node in the trie. This trades storage for latency &#8212; instead of traversing to all leaf nodes on every query, the answer is stored at the prefix node. Query time: O(len(prefix)) &#8212; just traverse down the trie.</span></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!H9At!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad79390c-d559-41d7-a8be-b9ade039d2a9_4500x2250.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!H9At!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad79390c-d559-41d7-a8be-b9ade039d2a9_4500x2250.png 424w, https://substackcdn.com/image/fetch/$s_!H9At!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad79390c-d559-41d7-a8be-b9ade039d2a9_4500x2250.png 848w, https://substackcdn.com/image/fetch/$s_!H9At!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad79390c-d559-41d7-a8be-b9ade039d2a9_4500x2250.png 1272w, https://substackcdn.com/image/fetch/$s_!H9At!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad79390c-d559-41d7-a8be-b9ade039d2a9_4500x2250.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!H9At!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad79390c-d559-41d7-a8be-b9ade039d2a9_4500x2250.png" width="1456" height="728" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ad79390c-d559-41d7-a8be-b9ade039d2a9_4500x2250.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:728,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:585119,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.systemdrd.com/i/204408046?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad79390c-d559-41d7-a8be-b9ade039d2a9_4500x2250.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!H9At!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad79390c-d559-41d7-a8be-b9ade039d2a9_4500x2250.png 424w, https://substackcdn.com/image/fetch/$s_!H9At!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad79390c-d559-41d7-a8be-b9ade039d2a9_4500x2250.png 848w, https://substackcdn.com/image/fetch/$s_!H9At!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad79390c-d559-41d7-a8be-b9ade039d2a9_4500x2250.png 1272w, https://substackcdn.com/image/fetch/$s_!H9At!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad79390c-d559-41d7-a8be-b9ade039d2a9_4500x2250.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><span>Without pre-computation: query time is O(all_suffixes) &#8212; must find all strings below the current node and rank them.</span></p><p><span>query_frequency table (offline aggregation source)</span></p><p><span>query_text, frequency_count, last_updated_at</span></p><p><span>This is the source of truth for what goes in the trie. Updated daily via a MapReduce / Spark job over the day&#8217;s search logs. The job counts query occurrences, normalizes (lowercase, trim), and writes the top-N queries per prefix into the trie build pipeline.</span></p><h3><span>Step 4 &#8212; Architecture</span></h3><p><span>Three components with different update cadences.</span></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!MADx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F284b08e7-6971-4167-aab6-209eb70b946e_4750x3250.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MADx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F284b08e7-6971-4167-aab6-209eb70b946e_4750x3250.png 424w, https://substackcdn.com/image/fetch/$s_!MADx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F284b08e7-6971-4167-aab6-209eb70b946e_4750x3250.png 848w, https://substackcdn.com/image/fetch/$s_!MADx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F284b08e7-6971-4167-aab6-209eb70b946e_4750x3250.png 1272w, https://substackcdn.com/image/fetch/$s_!MADx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F284b08e7-6971-4167-aab6-209eb70b946e_4750x3250.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!MADx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F284b08e7-6971-4167-aab6-209eb70b946e_4750x3250.png" width="1456" height="996" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/284b08e7-6971-4167-aab6-209eb70b946e_4750x3250.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:996,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:983226,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.systemdrd.com/i/204408046?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F284b08e7-6971-4167-aab6-209eb70b946e_4750x3250.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!MADx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F284b08e7-6971-4167-aab6-209eb70b946e_4750x3250.png 424w, https://substackcdn.com/image/fetch/$s_!MADx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F284b08e7-6971-4167-aab6-209eb70b946e_4750x3250.png 848w, https://substackcdn.com/image/fetch/$s_!MADx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F284b08e7-6971-4167-aab6-209eb70b946e_4750x3250.png 1272w, https://substackcdn.com/image/fetch/$s_!MADx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F284b08e7-6971-4167-aab6-209eb70b946e_4750x3250.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><span>Query service (read path &#8212; latency-critical)</span></p><p><span>1. Client types a character &#8594; sends GET /suggest?q=sea</span></p><p><span>2. Request hits a load balancer &#8594; routes to one of N </span><strong><span>Trie servers </span></strong><span>(in-memory trie, sharded by prefix range or consistent hash)</span></p><p><span>3. Trie server traverses the trie in O(len(query)) time &#8594; returns top-5 cached completions 4. Response cached at CDN edge (short TTL &#8212; 60 seconds) for common prefixes (typing &#8220;the&#8221; returns the same results for everyone)</span></p><p><span>5. Total latency: &lt; 10ms (CDN hit) or &lt; 50ms (trie server hit)</span></p><p><span>Trie build service (write path &#8212; offline, daily)</span></p><p><span>1. Raw search logs &#8594; Kafka &#8594; Spark/Flink streaming job</span></p><p><span>2. Aggregation job computes top-10M queries by frequency for the trailing 7 days</span></p><p><span>3. </span><strong><span>Trie builder </span></strong><span>constructs a new trie from scratch and pre-computes top-K at every node 4. New trie serialized to S3</span></p><p><span>5. Trie servers download and hot-swap the in-memory trie (blue-green style &#8212; new trie loaded in background, traffic cut over atomically)</span></p><p><strong><span>The hot-swap is the L5+ signal. </span></strong><span>Naive implementations rebuild the trie in place and serve stale or partially-built data during the rebuild. The correct approach: build the new trie entirely before serving any requests from it.</span></p><p><span>Trending query ingestion (real-time extension)</span></p><p><span>For real-time freshness (new trending query appears within minutes):</span></p><p><span>1. Search events stream to Kafka</span></p><p><span>2. A windowed aggregation job (5-minute tumbling window) identifies queries surging in frequency</span></p><p><span>3. Trending queries are injected into the trie via a small patch update (not a full rebuild) </span></p><p><span>4. Patch propagates to all trie servers via pub-sub</span></p><p><span>This is the L6 extension &#8212; daily batch covers the base case, real-time streaming handles trending. Name both.</span></p><div class="callout-block" data-callout="true"><p><span>Preparing for a distributed systems interview?</span><br><span>&#8594;</span><a href="https://systemdrd.com/ebooks/sdcourse-distributed-systems-interview">Download the free Interview Pack</a><br><span>&#8594; </span><a href="https://systemdr.systemdrd.com/subscribe">Subscribe</a><span> now to access source code repository - 200 + coding lessons</span></p></div>
      <p>
          <a href="https://systemdr.systemdrd.com/p/design-typeahead-search-autocomplete">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Reading the Interviewer]]></title><description><![CDATA[The system design interview is a conversation, not a presentation.]]></description><link>https://systemdr.systemdrd.com/p/reading-the-interviewer</link><guid isPermaLink="false">https://systemdr.systemdrd.com/p/reading-the-interviewer</guid><dc:creator><![CDATA[System Design Roadmap]]></dc:creator><pubDate>Sun, 19 Jul 2026 03:30:10 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!NGtO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7771f549-3768-4fb8-b23d-505d3cbaf61a_1052x570.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The system design interview is a conversation, not a presentation. The interviewer is giving you signals throughout the session. Most candidates miss them because they&#8217;re heads-down in their own design, narrating as they go, not watching the person on the other side of the table.</p><p>Here&#8217;s what those signals look like and what to do with each one.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">System Design Interview Roadmap is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p><strong>Signals that you&#8217;re on track</strong></p><p>&#8220;That&#8217;s interesting &#8212; tell me more about that.&#8221;</p><p>This is the best signal you can receive. The interviewer is engaged, they want to go deeper on something you said, and they&#8217;re inviting you to. Do it immediately. Whatever you were about to say next, pause it. Go deeper on the thing they asked about.</p><p>The mistake: treating this as confirmation that everything is fine and continuing your prepared flow. The interviewer told you where the interesting part of the question is. Follow them there.</p><p>Consistent nodding during a long explanation means you&#8217;re not losing them. Keep the same pace and depth.</p><p>A follow-up question that goes one level deeper on something you said &#8212; not redirecting to a new topic, but drilling into something you introduced &#8212; means the interviewer found your point substantive. This is different from a question that redirects you elsewhere</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NGtO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7771f549-3768-4fb8-b23d-505d3cbaf61a_1052x570.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NGtO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7771f549-3768-4fb8-b23d-505d3cbaf61a_1052x570.png 424w, https://substackcdn.com/image/fetch/$s_!NGtO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7771f549-3768-4fb8-b23d-505d3cbaf61a_1052x570.png 848w, https://substackcdn.com/image/fetch/$s_!NGtO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7771f549-3768-4fb8-b23d-505d3cbaf61a_1052x570.png 1272w, https://substackcdn.com/image/fetch/$s_!NGtO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7771f549-3768-4fb8-b23d-505d3cbaf61a_1052x570.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NGtO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7771f549-3768-4fb8-b23d-505d3cbaf61a_1052x570.png" width="1052" height="570" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7771f549-3768-4fb8-b23d-505d3cbaf61a_1052x570.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:570,&quot;width&quot;:1052,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:115057,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.systemdrd.com/i/198937869?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7771f549-3768-4fb8-b23d-505d3cbaf61a_1052x570.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!NGtO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7771f549-3768-4fb8-b23d-505d3cbaf61a_1052x570.png 424w, https://substackcdn.com/image/fetch/$s_!NGtO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7771f549-3768-4fb8-b23d-505d3cbaf61a_1052x570.png 848w, https://substackcdn.com/image/fetch/$s_!NGtO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7771f549-3768-4fb8-b23d-505d3cbaf61a_1052x570.png 1272w, https://substackcdn.com/image/fetch/$s_!NGtO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7771f549-3768-4fb8-b23d-505d3cbaf61a_1052x570.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Signals that you need to change direction</strong></p><p>&#8220;Let&#8217;s skip ahead to...&#8221; or &#8220;Actually, let&#8217;s focus on...&#8221;</p><p>The interviewer is redirecting you. This is not a signal that you did something wrong. It&#8217;s information: you&#8217;ve covered the previous section sufficiently, or you&#8217;re spending time on something that isn&#8217;t the probe they care about, or they have a specific component they want to evaluate and they&#8217;re efficiently navigating you there.</p><p>The correct response: stop mid-sentence if necessary. Don&#8217;t finish the paragraph. Say &#8220;Sure&#8221; and immediately go to where they&#8217;re pointing.</p><p>The wrong response: finishing your current point before the redirect. Taking 90 seconds to wrap up before pivoting. Explaining why you were going in the direction you were before changing direction.</p><p>None of these explanations are useful to the interviewer. The redirect supersedes everything else. Follow it immediately.</p><p>&#8220;What are the trade-offs?&#8221; immediately after you make a decision means: you stated the decision without justifying it. This is a probe, not a compliment. Answer it: what did you choose, what are you giving up, and what would change your mind.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe&quot;,&quot;text&quot;:&quot;Subscribe for Question Walkthrough&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://systemdr.systemdrd.com/subscribe"><span>Subscribe for Question Walkthrough</span></a></p><p><strong>Signals that you&#8217;ve misunderstood the question</strong></p><p>&#8220;What if this needs to work globally?&#8221;</p><p>&#8220;Let&#8217;s say the scale is 100&#215; what you assumed.&#8221;</p><p>&#8220;Actually, multiple users can edit the file simultaneously.&#8221;</p><p>These are corrections. Not gentle suggestions &#8212; the premise you&#8217;ve been designing for is wrong and the interviewer is telling you.</p><p>The correct response: stop, acknowledge once (&#8221;Good point &#8212; let me revise&#8221;), immediately build forward on the corrected premise.</p><p>The wrong response: defending the original premise, explaining why the correction doesn&#8217;t change things significantly, or taking two minutes to re-explain your reasoning before accepting the correction.</p><p>One acknowledgment, then forward. The interviewer doesn&#8217;t need to understand why you made the original assumption. They need to see you incorporate new information and keep moving.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!z1mh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe91add27-fe2d-4947-abfc-f2f502227ac4_2000x1125.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!z1mh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe91add27-fe2d-4947-abfc-f2f502227ac4_2000x1125.png 424w, https://substackcdn.com/image/fetch/$s_!z1mh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe91add27-fe2d-4947-abfc-f2f502227ac4_2000x1125.png 848w, https://substackcdn.com/image/fetch/$s_!z1mh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe91add27-fe2d-4947-abfc-f2f502227ac4_2000x1125.png 1272w, https://substackcdn.com/image/fetch/$s_!z1mh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe91add27-fe2d-4947-abfc-f2f502227ac4_2000x1125.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!z1mh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe91add27-fe2d-4947-abfc-f2f502227ac4_2000x1125.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e91add27-fe2d-4947-abfc-f2f502227ac4_2000x1125.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:334453,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.systemdrd.com/i/198937869?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe91add27-fe2d-4947-abfc-f2f502227ac4_2000x1125.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!z1mh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe91add27-fe2d-4947-abfc-f2f502227ac4_2000x1125.png 424w, https://substackcdn.com/image/fetch/$s_!z1mh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe91add27-fe2d-4947-abfc-f2f502227ac4_2000x1125.png 848w, https://substackcdn.com/image/fetch/$s_!z1mh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe91add27-fe2d-4947-abfc-f2f502227ac4_2000x1125.png 1272w, https://substackcdn.com/image/fetch/$s_!z1mh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe91add27-fe2d-4947-abfc-f2f502227ac4_2000x1125.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>The silence probe</strong></p><p>When you finish a section and the interviewer doesn&#8217;t immediately respond &#8212; they look at you, or look at the whiteboard, or just wait &#8212; this is almost always an invitation to go deeper.</p><p>The silence is not &#8220;that was fine, continue to the next section.&#8221; It&#8217;s &#8220;there&#8217;s more here, keep going.&#8221;</p><p>Most candidates treat silence as a signal to move on. The silence probe is actually the opposite: the interviewer has heard the surface answer and wants to see if you&#8217;ll surface the deeper one without being explicitly asked.</p><p>If you finish a section and get silence, don&#8217;t move to the next section. Go deeper on what you just said. Name a failure mode. Name a condition under which your design breaks. Name what you&#8217;d add with more time.</p><p>If you&#8217;ve genuinely exhausted the depth on that component, say so explicitly: &#8220;I think I&#8217;ve covered the core design here &#8212; should I move on to the data model?&#8221; This forces a response rather than leaving both of you in ambiguous silence.</p><p><strong>Using the interviewer actively</strong></p><p>The best candidate-interviewer dynamics aren&#8217;t interviews &#8212; they&#8217;re conversations. Candidates who treat the interviewer as a collaborator rather than an examiner consistently do better.</p><p>&#8220;I&#8217;m torn between two approaches here &#8212; let me think through both with you&#8221; is collaborative.</p><p>&#8220;I&#8217;m not sure which way this scales better &#8212; what factors would you weight more heavily?&#8221; is collaborative. It&#8217;s also information-gathering: if the interviewer says &#8220;I&#8217;d think about the write path specifically,&#8221; they&#8217;ve just told you where the probe is going.</p><p>This doesn&#8217;t mean delegating decisions to the interviewer. You still need to make choices and defend them. But using the interviewer as a thinking partner &#8212; bringing them into your reasoning process rather than presenting finished conclusions &#8212; produces a fundamentally different conversation.</p><p>That conversation is easier to score well on, because the interviewer has seen how you think, not just what you concluded.</p><div><hr></div><p><strong>CTA:</strong> The mock interview partners channel in the Discord is the fastest way to practice reading a real interviewer &#8212; not just a timer. Paid subscribers only.</p><h2><strong>Subscription link</strong></h2><p><a href="https://systemdr.systemdrd.com/subscribe">https://systemdr.systemdrd.com/subscribe</a></p><p>&#8212;Sumedh</p><div class="callout-block" data-callout="true"><p>The Question Vault has all 52 walkthroughs organized by archetype &#8212; so you can see the pattern across questions, not just the surface answer.</p><p><strong><span>Access all 52 Quesstions </span><a href="https://systemdrd.com/ebooks/52-faang-questions-drillcards-cheatsheets/">here</a></strong></p></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">System Design Interview Roadmap is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[LLM Inference Scaling: Techniques for Low-Latency Token Generation]]></title><description><![CDATA[Introduction]]></description><link>https://systemdr.systemdrd.com/p/llm-inference-scaling-techniques</link><guid isPermaLink="false">https://systemdr.systemdrd.com/p/llm-inference-scaling-techniques</guid><dc:creator><![CDATA[System Design Roadmap]]></dc:creator><pubDate>Fri, 17 Jul 2026 08:31:05 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!rk83!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4dda76eb-d4c5-420b-b2b7-631998623e8b_5060x3080.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2><blockquote><p>A user submits a prompt. The model generates 500 tokens. At 10 tokens/second, that&#8217;s 50 seconds of wall-clock time. At 100 tokens/second, it&#8217;s 5 seconds. The difference between those two numbers isn&#8217;t raw GPU power &#8212; it&#8217;s inference architecture. The same H100 cluster, configured differently, will produce radically different latency profiles. This article breaks down exactly why, and what production teams do about it.</p></blockquote><div><hr></div><h2>Why LLM Inference Is Uniquely Hard</h2><p>Unlike a CNN doing image classification, a large language model generating text is <strong>autoregressive</strong> &#8212; each output token depends on every token generated before it. You cannot parallelize generation across the output sequence. Token 50 must wait for token 49.</p><p>This creates two phases with completely different compute characteristics:</p><p><strong>Prefill</strong>: Processing the input prompt. The entire prompt is available at once, so this is highly parallelizable. It saturates GPU compute (FLOP-bound). A 1,000-token prompt takes roughly the same wall-clock time as a 10-token one on modern hardware.</p><p><strong>Decode</strong>: Generating output tokens one by one. Each step loads the entire model from GPU memory to compute a single token. This is memory-bandwidth-bound, not compute-bound. The GPU spends most of its time waiting on memory reads.</p><p>This asymmetry drives nearly every inference optimization.</p><div><hr></div><h2>KV Cache: The Non-Negotiable Foundation</h2><p>During attention computation, every transformer layer produces Key (K) and Value (V) tensors for each token. In autoregressive decode, if you recompute these from scratch on every step, you&#8217;re doing quadratic redundant work.</p><p>The KV cache stores K and V tensors from all previous tokens. Each decode step only needs to compute K/V for the <em>new</em> token, then attend over the cached history. This reduces per-step compute from O(n&#178;) to O(n).</p><blockquote><p>The cost: memory. A single KV cache entry for one token across all layers in a 70B-parameter model consumes roughly 0.5&#8211;2 MB depending on precision and architecture. A 4,096-token sequence holds several GB of KV data per concurrent request. At 100 concurrent users, you&#8217;re looking at hundreds of gigabytes &#8212; before model weights.</p></blockquote><p><strong>PagedAttention</strong> (introduced by the vLLM project) solved the fragmentation problem that plagued early KV cache implementations. Instead of pre-allocating a contiguous memory block per request (wasting space when sequences are shorter than the maximum), PagedAttention stores KV cache in fixed-size non-contiguous &#8220;pages,&#8221; similar to virtual memory in an OS. This improved GPU memory utilization from ~20&#8211;40% to over 90% in benchmarks on real workloads as of late 2024.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!rk83!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4dda76eb-d4c5-420b-b2b7-631998623e8b_5060x3080.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rk83!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4dda76eb-d4c5-420b-b2b7-631998623e8b_5060x3080.png 424w, https://substackcdn.com/image/fetch/$s_!rk83!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4dda76eb-d4c5-420b-b2b7-631998623e8b_5060x3080.png 848w, https://substackcdn.com/image/fetch/$s_!rk83!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4dda76eb-d4c5-420b-b2b7-631998623e8b_5060x3080.png 1272w, https://substackcdn.com/image/fetch/$s_!rk83!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4dda76eb-d4c5-420b-b2b7-631998623e8b_5060x3080.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!rk83!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4dda76eb-d4c5-420b-b2b7-631998623e8b_5060x3080.png" width="1456" height="886" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4dda76eb-d4c5-420b-b2b7-631998623e8b_5060x3080.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:886,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2316772,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.substack.com/i/191234144?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4dda76eb-d4c5-420b-b2b7-631998623e8b_5060x3080.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!rk83!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4dda76eb-d4c5-420b-b2b7-631998623e8b_5060x3080.png 424w, https://substackcdn.com/image/fetch/$s_!rk83!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4dda76eb-d4c5-420b-b2b7-631998623e8b_5060x3080.png 848w, https://substackcdn.com/image/fetch/$s_!rk83!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4dda76eb-d4c5-420b-b2b7-631998623e8b_5060x3080.png 1272w, https://substackcdn.com/image/fetch/$s_!rk83!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4dda76eb-d4c5-420b-b2b7-631998623e8b_5060x3080.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p>
      <p>
          <a href="https://systemdr.systemdrd.com/p/llm-inference-scaling-techniques">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Design a Distributed Rate Limiter — The Senior+ Walkthrough ]]></title><description><![CDATA[The rate limiter question is compact, deceptively hard, and asked everywhere.]]></description><link>https://systemdr.systemdrd.com/p/design-a-distributed-rate-limiter</link><guid isPermaLink="false">https://systemdr.systemdrd.com/p/design-a-distributed-rate-limiter</guid><dc:creator><![CDATA[System Design Roadmap]]></dc:creator><pubDate>Tue, 14 Jul 2026 02:27:09 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!gi0q!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdebdf120-5bd7-420a-b01d-f4890b0c2ddd_1517x800.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote><p><span>The rate limiter question is compact, deceptively hard, and asked everywhere. It tests whether you understand distributed systems coordination problems &#8212; specifically, how to enforce a global limit across a cluster of servers when no single server sees all requests. At L5 the probe is the algorithm choice. At L6 the probe is distributed coordination without a single point of failure.</span></p></blockquote><p><span>The Question</span></p><p><span>&#8220;Design a rate limiter. API clients are limited to N requests per second. Requests that exceed the limit return 429 Too Many Requests.&#8221;</span></p><p><span>Common variants: &#8220;Design Cloudflare&#8217;s rate limiting,&#8221; &#8220;Add rate limiting to a payment API,&#8221; &#8220;Design a per-user request quota system.&#8221;</span></p><h3><span>Step 1 &#8212; Clarify</span></h3><p><strong><span>1. What are we rate limiting on? </span></strong><span>Per IP, per user/API key, per endpoint, or combinations? Answer: typically per API key at the application level, per IP at the network edge.</span></p><p><strong><span>2. What granularity? </span></strong><span>Requests per second, per minute, per hour, per day? Multiple windows simultaneously (100 req/min AND 1,000 req/hour)?</span></p><p><strong><span>3. Hard limit or soft? </span></strong><span>Hard: the 101st request this minute is always rejected. Soft: occasional burst allowed. Most production systems use hard limits.</span></p><p><strong><span>4. Where does the limiter live? </span></strong><span>Middleware inside the API service, or a standalone sidecar/gateway? Standalone scales independently and is language-agnostic &#8212; correct answer for L5+.</span></p><p><strong><span>5. What&#8217;s the SLO? </span></strong><span>The rate limiter must add &lt; 1ms p99 latency to every request. It is in the hot path.</span></p><h3><span>Step 2 &#8212; Estimate</span></h3><p><span>- 50,000 API servers in a large deployment, each handling 10K req/sec - Total: 500M requests/sec &#8212; individual counters per API key must be updated atomically at this rate</span></p><p><span>- Redis cluster: 100K-500K ops/sec per node &#8212; need ~1,000-5,000 Redis nodes for 500M req/sec. In practice, shard by API key.</span></p><p><span>- Counter storage: 1M API keys &#215; 4 bytes per counter &#215; 60 windows = 240 MB &#8212; fits in memory</span></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe&quot;,&quot;text&quot;:&quot;Get Access to GitHub Repo&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://systemdr.systemdrd.com/subscribe"><span>Get Access to GitHub Repo</span></a></p><h3><span>Step 3 &#8212; API (internal interface)</span></h3><div class="callout-block" data-callout="true"><p><span>// Called by every API gateway before routing the request</span></p><p><span>bool allow_request(api_key: string, endpoint: string) &#8594; { allowed: bool, remaining: int, reset_at: epoch_ms }</span></p><p><span>// For the management API</span></p><p><span>PUT /v1/limits/:api_key { requests_per_minute: int, requests_per_hour: int } GET /v1/limits/:api_key/status &#8594; { current_count, limit, window_reset_at }</span></p></div><h3><span>Step 4 &#8212; Algorithm choice (the core probe)</span></h3><p><span>Four real algorithms. The senior answer names all four, picks one with justification, and explains what changes at L6.</span></p><p><span>Fixed window counter</span></p><p><span>Divide time into fixed 1-minute windows. Count requests per window per API key. Reset at window boundary.</span></p><p><strong><span>Win: </span></strong><span>Simple. O(1) time and space. One Redis INCR per request.</span></p><p><strong><span>Lose: </span></strong><span>Boundary burst problem. A client can send 100 requests at 12:00:59 and 100 more at 12:01:01 &#8212; that&#8217;s 200 requests in 2 seconds while the &#8220;limit&#8221; is 100/minute. The window reset creates a seam they can exploit.</span></p><p><span>Sliding window log</span></p><p><span>Store the timestamp of every request in the last 60 seconds. On each request, count entries in the log and reject if &gt; limit.</span></p><p><strong><span>Win: </span></strong><span>Perfectly accurate. No boundary burst.</span></p><p><strong><span>Lose: </span></strong><span>O(N) storage per API key (N = limit). For 1,000 req/min across 1M API keys, that&#8217;s 1 billion stored timestamps &#8212; expensive.</span></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Vne0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15f4e1e8-b08f-4290-b415-01a567b545fc_1625x777.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Vne0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15f4e1e8-b08f-4290-b415-01a567b545fc_1625x777.png 424w, https://substackcdn.com/image/fetch/$s_!Vne0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15f4e1e8-b08f-4290-b415-01a567b545fc_1625x777.png 848w, https://substackcdn.com/image/fetch/$s_!Vne0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15f4e1e8-b08f-4290-b415-01a567b545fc_1625x777.png 1272w, https://substackcdn.com/image/fetch/$s_!Vne0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15f4e1e8-b08f-4290-b415-01a567b545fc_1625x777.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Vne0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15f4e1e8-b08f-4290-b415-01a567b545fc_1625x777.png" width="1456" height="696" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/15f4e1e8-b08f-4290-b415-01a567b545fc_1625x777.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:696,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:242849,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.systemdrd.com/i/203661770?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15f4e1e8-b08f-4290-b415-01a567b545fc_1625x777.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Vne0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15f4e1e8-b08f-4290-b415-01a567b545fc_1625x777.png 424w, https://substackcdn.com/image/fetch/$s_!Vne0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15f4e1e8-b08f-4290-b415-01a567b545fc_1625x777.png 848w, https://substackcdn.com/image/fetch/$s_!Vne0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15f4e1e8-b08f-4290-b415-01a567b545fc_1625x777.png 1272w, https://substackcdn.com/image/fetch/$s_!Vne0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15f4e1e8-b08f-4290-b415-01a567b545fc_1625x777.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><span>Sliding window counter (hybrid) &#8592; correct answer for most interviews</span></p><p><span>Approximate the sliding window using two fixed-window counters: the current window and the previous window. Estimate the request count for the sliding window as:</span></p><p><span>rate = prev_count &#215; (1 - elapsed_fraction) + curr_count</span></p><p><span>Where elapsed_fraction = how far into the current window we are. If we&#8217;re 30 seconds into a 60-second window, the weight of the previous window is 0.5.</span></p><p><strong><span>Win: </span></strong><span>O(1) space per API key. Accurate within ~0.003% of the true sliding window (published by Cloudflare). No boundary burst exploit.</span></p><p><strong><span>Lose: </span></strong><span>Approximate (but the error is tiny). Slightly more complex than fixed window.</span></p><p><strong><span>This is what Cloudflare uses in production </span></strong><span>&#8212; they published a blog post on it. Saying &#8220;Cloudflare published their sliding window counter approach&#8221; is an L5+ signal.</span></p><p><span>Token bucket</span></p><p><span>Each API key has a bucket of capacity N tokens. Tokens refill at rate R per second. Each request consumes one token. If the bucket is empty, the request is rejected.</span></p><p><strong><span>Win: </span></strong><span>Allows controlled bursting &#8212; a client can use saved-up tokens in a burst. Better user experience for legitimate burst traffic.</span></p><p><strong><span>Lose: </span></strong><span>Two values to track per key (current tokens, last refill timestamp). Slightly harder to implement atomically.</span></p><p><strong><span>When to use: </span></strong><span>When the product requirement explicitly allows bursting (e.g., &#8220;allow up to 50 requests in any 1-second burst as long as the 1-minute average is under 100/min&#8221;). For strict per-second limits, sliding window counter is simpler.</span></p><p><strong><span>The senior recommendation: </span></strong><span>Default to sliding window counter (Cloudflare&#8217;s approach) for strict per-second/per-minute limits. Token bucket for burst-tolerant limits where the product explicitly needs it.</span></p><div class="callout-block" data-callout="true"><p>Preparing for a distributed systems interview?<br>&#8594;<a href="https://systemdrd.com/ebooks/sdcourse-distributed-systems-interview">Download the free Interview Pack</a><br>&#8594; <a href="https://systemdr.systemdrd.com/subscribe">Subscribe</a> now to access source code repository - 200 + coding lessons</p></div>
      <p>
          <a href="https://systemdr.systemdrd.com/p/design-a-distributed-rate-limiter">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Offers landed — What the Spring Cohort got right]]></title><description><![CDATA[Learn System Design with System building, Subscribe Hands On coding course - LogStream]]></description><link>https://systemdr.systemdrd.com/p/offers-landed-what-the-best-prepared</link><guid isPermaLink="false">https://systemdr.systemdrd.com/p/offers-landed-what-the-best-prepared</guid><dc:creator><![CDATA[System Design Roadmap]]></dc:creator><pubDate>Sun, 12 Jul 2026 03:30:29 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!kno5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F499f4983-bf92-48d5-ad8e-31a85d9636fa_5060x2860.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="callout-block" data-callout="true"><p>Learn <strong>System Design with System building, Subscribe Hands On coding course - <a href="https://sdcourse.substack.com/p/start-here-how-to-use-sdcourse">LogStream</a></strong></p></div><p>Every few weeks, someone posts in the Discord&#8217;s <code>#offers-landed</code> channel. L5 at Google. Senior at Stripe. Staff at DoorDash. L6 at Meta after two prior failed loops.</p><p>I read every one. After enough of them, patterns become visible. The engineers who pass consistently are not uniformly technically stronger than the ones who fail. They are systematically different in three specific ways.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">System Design Interview Roadmap is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p><strong>They scope, then go deep. Not the other way around.</strong></p><p>The most common failure mode I hear in post-mortems from engineers who got &#8220;No Hire&#8221; is some version of: &#8220;I designed a great system but ran out of time before the hard part.&#8221;</p><blockquote><p>Every engineer who has passed at L5 or above in the last six months has told me some version of the same thing: they spent the first five minutes explicitly scoping &#8212; &#8220;I&#8217;m going to focus on the timeline and the fan-out architecture, and I&#8217;m going to acknowledge but not design the notifications, search, and ads&#8221; &#8212; and then went deep on the one component they chose.</p></blockquote><p>The engineers who fail design everything shallowly. The engineers who pass design one thing deeply.</p><blockquote><p>This is not a trivial shift. Most engineers feel obligated to cover everything. The pressure to show breadth is real. Resisting it and committing to depth in the first five minutes is a deliberate choice that requires practice.</p></blockquote><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!kno5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F499f4983-bf92-48d5-ad8e-31a85d9636fa_5060x2860.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!kno5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F499f4983-bf92-48d5-ad8e-31a85d9636fa_5060x2860.png 424w, https://substackcdn.com/image/fetch/$s_!kno5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F499f4983-bf92-48d5-ad8e-31a85d9636fa_5060x2860.png 848w, https://substackcdn.com/image/fetch/$s_!kno5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F499f4983-bf92-48d5-ad8e-31a85d9636fa_5060x2860.png 1272w, https://substackcdn.com/image/fetch/$s_!kno5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F499f4983-bf92-48d5-ad8e-31a85d9636fa_5060x2860.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!kno5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F499f4983-bf92-48d5-ad8e-31a85d9636fa_5060x2860.png" width="1456" height="823" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/499f4983-bf92-48d5-ad8e-31a85d9636fa_5060x2860.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:823,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:904747,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.systemdrd.com/i/198937705?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F499f4983-bf92-48d5-ad8e-31a85d9636fa_5060x2860.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!kno5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F499f4983-bf92-48d5-ad8e-31a85d9636fa_5060x2860.png 424w, https://substackcdn.com/image/fetch/$s_!kno5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F499f4983-bf92-48d5-ad8e-31a85d9636fa_5060x2860.png 848w, https://substackcdn.com/image/fetch/$s_!kno5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F499f4983-bf92-48d5-ad8e-31a85d9636fa_5060x2860.png 1272w, https://substackcdn.com/image/fetch/$s_!kno5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F499f4983-bf92-48d5-ad8e-31a85d9636fa_5060x2860.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe&quot;,&quot;text&quot;:&quot;Subscribe for Question Walkthrough&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://systemdr.systemdrd.com/subscribe"><span>Subscribe for Question Walkthrough</span></a></p><p><strong>They say the hard thing out loud before the interviewer asks.</strong></p><p>The standard pattern in a design interview is: candidate draws the happy path, interviewer probes the failure case, candidate scrambles to address it.</p><p>The pattern in successful candidates is different: candidate draws the happy path, then immediately says &#8220;the part of this design I&#8217;m most concerned about is the thundering herd when the cache node recovers &#8212; let me address that.&#8221; The probe never comes because the candidate already went there.</p><p>This signals something important: not just that you know the failure mode, but that you think about your own designs critically. That&#8217;s the operational maturity signal. It&#8217;s very hard to fake, and it&#8217;s very clear when it&#8217;s present.</p><p><strong>They treat the interviewer as a collaborator, not an examiner.</strong></p><p>This one is harder to describe but unmistakable when you see it.</p><p>Candidates who fail tend to treat the design round as a test &#8212; something being administered to them. They present, the interviewer asks, they defend. The dynamic is adversarial even when the interviewer is trying to be helpful.</p><p>Candidates who pass tend to use the interviewer. &#8220;I&#8217;m considering two approaches here &#8212; let me think through both with you.&#8221; &#8220;Does this constraint change which way you&#8217;d go?&#8221; &#8220;I&#8217;m not sure which way this scales better &#8212; what&#8217;s your intuition?&#8221;</p><p>This works for two reasons. First, it makes the interview feel collaborative, which influences the interviewer&#8217;s overall impression. Second, and more importantly, it gets you real information. When you say &#8220;I&#8217;m torn between these two approaches&#8221; and the interviewer says &#8220;let&#8217;s explore the second one,&#8221; they&#8217;ve just told you where the interesting part of the question is. That&#8217;s not cheating &#8212; that&#8217;s good communication.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!K5t2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4459bdf2-867a-40e3-9316-f3130616de40_4950x2640.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!K5t2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4459bdf2-867a-40e3-9316-f3130616de40_4950x2640.png 424w, https://substackcdn.com/image/fetch/$s_!K5t2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4459bdf2-867a-40e3-9316-f3130616de40_4950x2640.png 848w, https://substackcdn.com/image/fetch/$s_!K5t2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4459bdf2-867a-40e3-9316-f3130616de40_4950x2640.png 1272w, https://substackcdn.com/image/fetch/$s_!K5t2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4459bdf2-867a-40e3-9316-f3130616de40_4950x2640.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!K5t2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4459bdf2-867a-40e3-9316-f3130616de40_4950x2640.png" width="1456" height="777" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4459bdf2-867a-40e3-9316-f3130616de40_4950x2640.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:777,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:713389,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.systemdrd.com/i/198937705?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4459bdf2-867a-40e3-9316-f3130616de40_4950x2640.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!K5t2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4459bdf2-867a-40e3-9316-f3130616de40_4950x2640.png 424w, https://substackcdn.com/image/fetch/$s_!K5t2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4459bdf2-867a-40e3-9316-f3130616de40_4950x2640.png 848w, https://substackcdn.com/image/fetch/$s_!K5t2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4459bdf2-867a-40e3-9316-f3130616de40_4950x2640.png 1272w, https://substackcdn.com/image/fetch/$s_!K5t2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4459bdf2-867a-40e3-9316-f3130616de40_4950x2640.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>What these three things have in common</strong></p><p>None of them are technical. Scoping, self-critique, and collaboration are all communication skills. They&#8217;re skills you can practice in a mock interview. You cannot practice them by reading another walkthrough.</p><p>The most common mistake I see in prep is the ratio: 90% reading walkthroughs, 10% timed drills with feedback. The engineers who pass consistently tend to invert that ratio in the final 4 weeks before the interview.</p><p>The knowledge is necessary. It&#8217;s just not sufficient.</p><p>If you&#8217;ve been reading this newsletter and feel solid on the technical content, the thing to do next is not to read more. It&#8217;s to schedule a mock with someone who will score you honestly on scoping, critique, and collaboration &#8212; not just on whether you knew consistent hashing.</p><div><hr></div><p><strong>CTA:</strong> </p><p>Paid subscribers get one full system design walkthrough </p><p>every Tuesday &#8212; each mapped to its archetype so you build </p><p>pattern recognition, not answer memorization. </p><p>This week:  Rate Limiter.</p><h2><strong>Subscription link</strong></h2><p><a href="https://systemdr.systemdrd.com/subscribe">https://systemdr.systemdrd.com/subscribe</a></p><p>&#8212;Sumedh</p><p><strong>Curious how this works in real systems?</strong> </p><p>The paid lessons cover scalability, optimization, and real-world engineering patterns.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">System Design Interview Roadmap is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[RAG Architecture — Designing Context-Aware AI Systems]]></title><description><![CDATA[Introduction]]></description><link>https://systemdr.systemdrd.com/p/rag-architecture-designing-context</link><guid isPermaLink="false">https://systemdr.systemdrd.com/p/rag-architecture-designing-context</guid><dc:creator><![CDATA[System Design Roadmap]]></dc:creator><pubDate>Fri, 10 Jul 2026 08:37:18 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!DZ7v!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae68f144-27cf-4e14-a517-7b83a63b3702_3740x2530.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2><blockquote><p>You ship a customer-facing chatbot backed by GPT-4. It answers 80% of questions brilliantly. Then a user asks about a product SKU you added last week, a policy change from this morning, or a support ticket filed an hour ago. The model hallucinates confidently. The problem isn&#8217;t the model &#8212; it&#8217;s that the model&#8217;s weights are frozen in time and isolated from your operational data. Retrieval-Augmented Generation (RAG) is the architectural pattern that closes that gap: it lets a language model reason over <em>your</em> data, <em>now</em>, without retraining.</p></blockquote><div><hr></div><div class="callout-block" data-callout="true"><p><span>The gap between a &#8220;system design interview&#8221; and a &#8220;production system&#8221; is massive. &#8220;</span><strong><span>Hands On Distributed System Design Course</span></strong><span>&#8221; newsletter exists to bridge that gap. If you are working for any company no one is going to teach you how system is design or built. Fun part developers rarely document everything. you need to dig through to understand the system. </span><a href="https://sdcourse.substack.com/subscribe">Learn from scratch. Access Private Git Repo Now</a><span>.</span></p></div><h2>Core Concept: What RAG Actually Does</h2><p>A language model is a frozen function. Its weights encode general world knowledge up to a training cutoff; it cannot access your database, your docs, your tickets. RAG separates the <em>retrieval</em> problem from the <em>reasoning</em> problem.</p><p>The pattern works in two phases:</p><p><strong>Indexing phase (offline):</strong> Source documents &#8212; PDFs, markdown files, database rows, Confluence pages &#8212; are chunked into segments, typically 256&#8211;512 tokens. Each chunk is embedded into a high-dimensional vector using a model like <code>text-embedding-3-small</code> or <code>bge-large-en</code>. These vectors are stored in a vector database (Pinecone, Weaviate, pgvector, Qdrant). This phase runs continuously as data changes.</p><p><strong>Query phase (online):</strong> When a user submits a query, that query is embedded using the <em>same</em> embedding model. The vector store performs approximate nearest-neighbor (ANN) search &#8212; cosine or dot-product similarity &#8212; returning the top-k most semantically similar chunks, typically k=3&#8211;10. Those chunks are injected into the LLM prompt as context. The model reasons over retrieved evidence rather than relying solely on its weights.</p><p>The critical architectural insight: the LLM is doing <em>grounded reading comprehension</em>, not recall. This is fundamentally different from how models are typically deployed.</p><p><strong>Chunking strategy is load-bearing.</strong> If chunks are too large, you waste context tokens and dilute relevance. Too small, and you lose surrounding context needed to answer coherently. Semantic chunking &#8212; splitting at paragraph or section boundaries rather than fixed token counts &#8212; outperforms naive sliding windows. Hierarchical chunking (summary chunk + child detail chunk) handles both coarse-grained and fine-grained queries.</p><p><strong>Embedding model selection affects recall ceiling.</strong> Retrieval quality is bounded by how well the embedding model captures semantic similarity for your domain. General-purpose models underperform on specialized corpora (legal, medical, code). Fine-tuning an embedding model on domain-specific positive/negative pairs &#8212; contrastive training &#8212; measurably improves recall. This step is skipped in most initial deployments and becomes the dominant bottleneck at scale.</p><p><strong>Reranking separates relevant from merely similar.</strong> First-pass ANN retrieval optimizes for speed using approximate algorithms (HNSW, IVF). A reranker &#8212; typically a cross-encoder model like Cohere Rerank or a fine-tuned BERT &#8212; takes the top-50 ANN results and re-scores them with full cross-attention between query and document. Reranking improves precision substantially and adds 20&#8211;100ms latency. At production scale, you run the reranker only when the primary retrieval confidence is below a threshold.</p><p><strong>Hybrid search outperforms pure vector search for most production workloads.</strong> Combining dense vector similarity with sparse BM25 retrieval (keyword matching) via reciprocal rank fusion (RRF) handles cases where exact-match terms &#8212; product IDs, error codes, names &#8212; would be missed by semantic search alone. Elasticsearch and OpenSearch support this natively; Weaviate and Qdrant have hybrid modes.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!DZ7v!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae68f144-27cf-4e14-a517-7b83a63b3702_3740x2530.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!DZ7v!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae68f144-27cf-4e14-a517-7b83a63b3702_3740x2530.png 424w, https://substackcdn.com/image/fetch/$s_!DZ7v!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae68f144-27cf-4e14-a517-7b83a63b3702_3740x2530.png 848w, https://substackcdn.com/image/fetch/$s_!DZ7v!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae68f144-27cf-4e14-a517-7b83a63b3702_3740x2530.png 1272w, https://substackcdn.com/image/fetch/$s_!DZ7v!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae68f144-27cf-4e14-a517-7b83a63b3702_3740x2530.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!DZ7v!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae68f144-27cf-4e14-a517-7b83a63b3702_3740x2530.png" width="1456" height="985" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ae68f144-27cf-4e14-a517-7b83a63b3702_3740x2530.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:985,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:445981,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.substack.com/i/191234122?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae68f144-27cf-4e14-a517-7b83a63b3702_3740x2530.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!DZ7v!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae68f144-27cf-4e14-a517-7b83a63b3702_3740x2530.png 424w, https://substackcdn.com/image/fetch/$s_!DZ7v!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae68f144-27cf-4e14-a517-7b83a63b3702_3740x2530.png 848w, https://substackcdn.com/image/fetch/$s_!DZ7v!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae68f144-27cf-4e14-a517-7b83a63b3702_3740x2530.png 1272w, https://substackcdn.com/image/fetch/$s_!DZ7v!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae68f144-27cf-4e14-a517-7b83a63b3702_3740x2530.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div>
      <p>
          <a href="https://systemdr.systemdrd.com/p/rag-architecture-designing-context">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Design Google Drive / Dropbox — The Senior+ Walkthrough]]></title><description><![CDATA[This is the question that defines the file sync and storage archetype.]]></description><link>https://systemdr.systemdrd.com/p/design-google-drive-dropbox-the-senior</link><guid isPermaLink="false">https://systemdr.systemdrd.com/p/design-google-drive-dropbox-the-senior</guid><dc:creator><![CDATA[System Design Roadmap]]></dc:creator><pubDate>Tue, 07 Jul 2026 01:30:37 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!LXhg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F91f60f9d-9f97-41bc-805a-63f668f5be01_468x306.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote><p><span>This is the question that defines the file sync and storage archetype. Eight questions in the question bank are variants &#8212; iCloud Photos, distributed file systems, cloud backup services, Git-style version control storage, CDN edge caching. They share a spine: chunked file storage, metadata management, multi-device consistency, and conflict resolution. Internalize this one and you can answer all eight.</span></p></blockquote><blockquote><p><span>The surface question sounds like object storage with a UI. The probe underneath is what separates candidates: </span><strong><span>what happens when two devices modify the same file simultaneously? </span></strong><span>That conflict resolution problem &#8212; deceptively simple on the surface, genuinely hard in distributed systems &#8212; is where every L5+ interview on this question goes.</span></p></blockquote><blockquote><p><span>For L4 / mid-level: upload/download flow and basic chunked storage. For L5 / senior: delta sync (only transfer what changed, not the whole file), deduplication, and conflict detection. For L6 / staff: vector clocks or last-writer-wins with operational transforms for true conflict resolution, the consistency model across devices, and what Dropbox actually does differently from naive S3.</span></p></blockquote><p><span>The Question</span></p><p><span>&#8220;Design Google Drive or Dropbox. Users upload files from their devices. Files are accessible from any of their devices and sync automatically when changed.&#8221;</span></p><p><span>Common variants:</span></p><p><span>- &#8220;Design iCloud Drive / Apple Files.&#8221;</span></p><p><span>- &#8220;Design a cloud backup service.&#8221;</span></p><p><span>- &#8220;Design the file sync layer for a collaborative tool.&#8221;</span></p><p><span>- &#8220;Design a distributed file system.&#8221;</span></p><h3><span>Step 1 &#8212; Clarify Before You Draw</span></h3><p><strong><span>1. Individual file storage or collaborative editing? </span></strong><span>Dropbox stores files &#8212; one writer at a time, sync on save. Google Docs is collaborative editing &#8212; multiple simultaneous writers with operational transforms. These are fundamentally different systems. Clarify and scope to Dropbox-style unless told otherwise.</span></p><p><strong><span>2. What file types and size limits? </span></strong><span>Documents, images, video &#8212; or everything? Max file size matters: Dropbox supports files up to 50 GB. A naive single-upload approach collapses above a few hundred MB.</span></p><p><strong><span>3. Multi-device sync &#8212; how many devices per user? </span></strong><span>Average user: 3&#8211;5 devices. Power user: 10+. Each device must receive all changes to synced folders. This drives the notification and sync architecture.</span></p><p><strong><span>4. Versioning and deleted file recovery? </span></strong><span>Most cloud storage products retain file versions (Dropbox keeps 30&#8211;180 days of version history). Deleted files go to trash with a retention window. State the assumptions.</span></p><p><strong><span>5. What scale? </span></strong><span>Dropbox at its peak: 700 million registered users, 500 million files uploaded per day. Working assumptions: 100M DAU, 1B files stored, average file size 1 MB.</span></p><p><strong><span>6. What&#8217;s the SLO? </span></strong><span>File upload acknowledges within 5 seconds for files under 10 MB. Sync propagates to other devices within 30 seconds of the change. These two SLOs drive the architecture.</span></p><h3><span>Step 2 &#8212; Estimate</span></h3><p><span>- 100M DAU, each uploads/modifies ~5 files/day average &#8594; 500M file operations/day &#8594; ~5,800 ops/sec</span></p><p><span>- Average file size 1 MB &#8594; 5.8 TB/day of new or modified data ingested - Total files stored: 1B files &#215; 1 MB average = 1 PB</span></p><p><span>- With deduplication (identical files stored once): real storage closer to 400&#8211;600 TB (60% dedup ratio is typical)</span></p><p><span>- Metadata per file: ~500 bytes (name, path, size, hash, version, owner, timestamps) &#8594; 500 bytes &#215; 1B files = 500 GB of metadata &#8212; fits comfortably in a sharded relational database</span></p><p><span>- Change notifications: 500M operations/day / 86,400 seconds &#215; 3 devices per user average = ~17,000 notification fanouts/sec</span></p><p><span>The deduplication estimate is the senior signal in estimation. Dropbox publicly states that deduplication dramatically reduces storage costs because many users store the same files (PDFs, installers, stock photos). Mentioning deduplication in the estimation shows you&#8217;ve thought about the system&#8217;s economics, not just its architecture.</span></p><div class="callout-block" data-callout="true"><p><strong><mark data-color="#ffff00" style="background-color: rgb(255, 255, 0); color: rgb(0, 0, 0);">52 FAANG Question Vault</mark></strong> &#8212; $299 one-time (or $249 for paid subscribers)</p><p>All 52 walkthroughs + 52 drill cards + 6 framework cheatsheets + the Senior+ System Design Playbook. Everything, immediately. Lifetime access with all future updates included. &#8594; [<a href="https://systemdrd.com/ebooks/52-faang-questions-drillcards-cheatsheets/">VAULT CHECKOUT LINK</a>]</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe&quot;,&quot;text&quot;:&quot;Get Access to GitHub Repo&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://systemdr.systemdrd.com/subscribe"><span>Get Access to GitHub Repo</span></a></p><div><hr></div><h3><span>Step 3 &#8212; API Design</span></h3><div class="callout-block" data-callout="true"><p><span>POST /v1/files/upload/init</span></p><p><span>Body: { file_name, file_size_bytes, content_hash_sha256, parent_folder_id } Response: {</span></p><p><span>upload_id: string,</span></p><p><span>upload_urls: [{ chunk_index, presigned_s3_url }], &#8592; chunked upload</span></p><p><span>chunk_size_bytes: 4194304 (4 MB)</span></p><p><span>}</span></p><p><span>PUT {presigned_s3_url} (direct to S3 &#8212; server not in the upload path)</span></p><p><span>Body: binary chunk data</span></p><p><span>POST /v1/files/upload/complete</span></p><p><span>Body: { upload_id, chunk_etags: [{ chunk_index, etag }] }</span></p><p><span>Response: { file_id, version_id, path, created_at }</span></p><p><span>GET /v1/files/:file_id/download</span></p><p><span>Response: { presigned_download_url, expires_at }</span></p><p><span>GET /v1/sync/changes</span></p><p><span>Query: { cursor: string, limit: int } &#8592; long-poll or SSE</span></p><p><span>Response: { changes: [...], new_cursor: string, has_more: bool }</span></p><p><span>POST /v1/files/:file_id/conflict</span></p><p><span>Body: { </span></p><p><span>local_version_id, server_version_id, resolution: &#8220;keep_local&#8221; | &#8220;keep_server&#8221; | &#8220;keep_both&#8221; </span></p><p><span>}</span></p><p><strong><span>The senior moves on this API:</span></strong></p></div><p><strong><span>Chunked upload with presigned URLs. </span></strong><span>Files go directly from the client to S3 &#8212; the API server never handles the binary data. This eliminates the API tier as a bandwidth bottleneck. The upload_id ties the chunks together; the etags from each chunk PUT allow S3 to assemble the final object via S3 multipart upload completion.</span></p><p><strong><span>The /sync/changes endpoint with cursors. </span></strong><span>This is the Dropbox API model (they call it list_folder/continue). Instead of polling &#8220;what changed since timestamp X,&#8221; the client maintains an opaque cursor that encodes its sync state. The server returns everything the client has missed since that cursor position. This handles offline sync correctly: a device that was offline for 2 weeks reconnects, passes its cursor, and gets all 2 weeks of changes in one call.</span></p><p><strong><span>The /conflict endpoint. </span></strong><span>Most candidates forget this exists. Conflict resolution is a user-facing operation &#8212; the client detects a conflict, shows the user, and the user or the system decides. Having an explicit endpoint for conflict resolution signals you&#8217;ve thought about the user-facing side of the distributed systems problem.</span></p><h3><span>Step 4 &#8212; Data Model</span></h3><p><span>files table</span></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!OZl2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a0540c8-d1aa-4f5e-95db-38927f815ee5_932x386.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!OZl2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a0540c8-d1aa-4f5e-95db-38927f815ee5_932x386.png 424w, https://substackcdn.com/image/fetch/$s_!OZl2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a0540c8-d1aa-4f5e-95db-38927f815ee5_932x386.png 848w, https://substackcdn.com/image/fetch/$s_!OZl2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a0540c8-d1aa-4f5e-95db-38927f815ee5_932x386.png 1272w, https://substackcdn.com/image/fetch/$s_!OZl2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a0540c8-d1aa-4f5e-95db-38927f815ee5_932x386.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!OZl2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a0540c8-d1aa-4f5e-95db-38927f815ee5_932x386.png" width="932" height="386" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1a0540c8-d1aa-4f5e-95db-38927f815ee5_932x386.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:386,&quot;width&quot;:932,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:56076,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.systemdrd.com/i/203652121?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a0540c8-d1aa-4f5e-95db-38927f815ee5_932x386.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!OZl2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a0540c8-d1aa-4f5e-95db-38927f815ee5_932x386.png 424w, https://substackcdn.com/image/fetch/$s_!OZl2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a0540c8-d1aa-4f5e-95db-38927f815ee5_932x386.png 848w, https://substackcdn.com/image/fetch/$s_!OZl2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a0540c8-d1aa-4f5e-95db-38927f815ee5_932x386.png 1272w, https://substackcdn.com/image/fetch/$s_!OZl2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a0540c8-d1aa-4f5e-95db-38927f815ee5_932x386.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qnXd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffeed24e7-3438-4a88-9fec-2891c3fb2b99_937x472.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qnXd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffeed24e7-3438-4a88-9fec-2891c3fb2b99_937x472.png 424w, https://substackcdn.com/image/fetch/$s_!qnXd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffeed24e7-3438-4a88-9fec-2891c3fb2b99_937x472.png 848w, https://substackcdn.com/image/fetch/$s_!qnXd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffeed24e7-3438-4a88-9fec-2891c3fb2b99_937x472.png 1272w, https://substackcdn.com/image/fetch/$s_!qnXd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffeed24e7-3438-4a88-9fec-2891c3fb2b99_937x472.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qnXd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffeed24e7-3438-4a88-9fec-2891c3fb2b99_937x472.png" width="937" height="472" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/feed24e7-3438-4a88-9fec-2891c3fb2b99_937x472.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:472,&quot;width&quot;:937,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:96715,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.systemdrd.com/i/203652121?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffeed24e7-3438-4a88-9fec-2891c3fb2b99_937x472.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!qnXd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffeed24e7-3438-4a88-9fec-2891c3fb2b99_937x472.png 424w, https://substackcdn.com/image/fetch/$s_!qnXd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffeed24e7-3438-4a88-9fec-2891c3fb2b99_937x472.png 848w, https://substackcdn.com/image/fetch/$s_!qnXd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffeed24e7-3438-4a88-9fec-2891c3fb2b99_937x472.png 1272w, https://substackcdn.com/image/fetch/$s_!qnXd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffeed24e7-3438-4a88-9fec-2891c3fb2b99_937x472.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong><span>The content_hash &#8594; storage_key mapping is the deduplication mechanism. </span></strong><span>Before storing a file, the server checks whether content_hash already exists in the storage index. If it does, it reuses the existing S3 object and just creates a new metadata row pointing to it. The same file can be &#8220;owned&#8221; by millions of users but stored in S3 once.</span></p><blockquote><p><span>file_versions table</span></p></blockquote><p><span>version_id, file_id (FK), version_number, content_hash, size_bytes,</span></p><p><span>storage_key, created_by_device_id, created_at, is_current</span></p><p><span>Every modification creates a new version row. The is_current flag moves to the newest version. Old versions are retained for 30 days (configurable), then the storage_key reference is eligible for deletion if no other version or file points to it.</span></p><blockquote><p><span>sync_cursors table</span></p></blockquote><p><span>cursor_id, device_id, user_id, last_processed_change_id, updated_at</span></p><p><span>Each device has a cursor. When the device calls /sync/changes, the server returns all changes after last_processed_change_id for that user, then updates the cursor. The cursor is device-specific, not user-specific &#8212; each device tracks its own sync position independently.</span></p><p><span>change_log table &#8212; the sync feed</span></p><p><span>change_id (SEQUENTIAL), user_id (INDEXED), file_id, change_type</span></p><p><span>(created/modified/deleted/moved),</span></p><p><span>version_id, changed_by_device_id, changed_at</span></p><p><span>This is the append-only event log that drives sync. Every file operation appends a row. When a device calls /sync/changes?cursor=X, the query is simply: SELECT * FROM change_log WHERE user_id=:uid AND change_id &gt; :cursor_change_id ORDER BY change_id LIMIT :limit. Fast, simple, correct.</span></p><p><span>The change_id is a sequential integer (not UUID). Sequential IDs make the range query above maximally efficient. They can be generated by Postgres sequences on a per-user basis, or by a distributed ID sequence (Snowflake-style, with the user_id encoded in the ID).</span></p>
      <p>
          <a href="https://systemdr.systemdrd.com/p/design-google-drive-dropbox-the-senior">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[The 30 Days Before Your Onsite]]></title><description><![CDATA[Learn System Design with System building, Subscribe Hands On coding course - LogStream]]></description><link>https://systemdr.systemdrd.com/p/the-30-days-before-your-onsite</link><guid isPermaLink="false">https://systemdr.systemdrd.com/p/the-30-days-before-your-onsite</guid><dc:creator><![CDATA[System Design Roadmap]]></dc:creator><pubDate>Sun, 05 Jul 2026 03:30:50 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!9fp5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffd8a98f8-87c5-4711-b5be-e6a23cf7ba38_2000x1125.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="callout-block" data-callout="true"><p><span>Learn </span><strong><span>System Design with System building, Subscribe Hands On coding course - </span><a href="https://sdcourse.substack.com/p/start-here-how-to-use-sdcourse">LogStream</a></strong></p></div><p>Thirty days. One onsite loop. Here&#8217;s the plan I&#8217;d actually follow &#8212; not the plan that covers everything, because thirty days cannot cover everything, but the plan that prepares you for the specific interview in front of you.</p><p><strong>The principle: targeted depth beats broad coverage</strong></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">System Design Interview Roadmap is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>Thirty days of prep that covers six archetypes shallowly will lose to twenty days of prep that covers two archetypes deeply, plus ten days of mock interviews.</p><p>The engineers who pass consistently aren&#8217;t universally prepared. They&#8217;re specifically well-prepared for the questions they&#8217;re most likely to face. At most companies, a single loop involves one or two system design questions. If you know your target company&#8217;s interview patterns, you know which two archetypes to prioritize.</p><p>Research your target company before you start prep. Look at Glassdoor, Blind, and LinkedIn connections who&#8217;ve interviewed there recently. Identify the two most commonly asked archetypes. Those are your week 1 and week 2.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe&quot;,&quot;text&quot;:&quot;Subscribe for Question Walkthrough&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://systemdr.systemdrd.com/subscribe"><span>Subscribe for Question Walkthrough</span></a></p><p><strong>Week 1 (Days 1&#8211;7): Deep drill, archetype #1</strong></p><p>Pick the most likely archetype for your target company. Read two walkthroughs from that archetype fully. Don&#8217;t drill yet &#8212; read to understand the pattern.</p><p>Then do three timed cold drills from that archetype on days 3, 5, and 7:</p><ul><li><p>Set a 50-minute timer</p></li><li><p>Design on paper with no notes, no searching</p></li><li><p>When the timer ends, open the walkthrough and compare section by section</p></li><li><p>Write down the top 3 specific gaps between your answer and the walkthrough</p></li></ul><p>By day 7, you should produce a structurally correct answer &#8212; not perfect, but with the right components in the right places and the key failure modes named.</p><p><strong>Week 2 (Days 8&#8211;14): Deep drill, archetype #2</strong></p><p>Same structure. Different archetype &#8212; your second most likely one.</p><p>After two weeks, you have deep coverage of the two archetypes most likely to come up. That alone puts you in better position than most candidates who drilled 15 questions shallowly.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9fp5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffd8a98f8-87c5-4711-b5be-e6a23cf7ba38_2000x1125.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9fp5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffd8a98f8-87c5-4711-b5be-e6a23cf7ba38_2000x1125.png 424w, https://substackcdn.com/image/fetch/$s_!9fp5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffd8a98f8-87c5-4711-b5be-e6a23cf7ba38_2000x1125.png 848w, https://substackcdn.com/image/fetch/$s_!9fp5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffd8a98f8-87c5-4711-b5be-e6a23cf7ba38_2000x1125.png 1272w, https://substackcdn.com/image/fetch/$s_!9fp5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffd8a98f8-87c5-4711-b5be-e6a23cf7ba38_2000x1125.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9fp5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffd8a98f8-87c5-4711-b5be-e6a23cf7ba38_2000x1125.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fd8a98f8-87c5-4711-b5be-e6a23cf7ba38_2000x1125.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:271647,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.systemdrd.com/i/198937553?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffd8a98f8-87c5-4711-b5be-e6a23cf7ba38_2000x1125.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!9fp5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffd8a98f8-87c5-4711-b5be-e6a23cf7ba38_2000x1125.png 424w, https://substackcdn.com/image/fetch/$s_!9fp5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffd8a98f8-87c5-4711-b5be-e6a23cf7ba38_2000x1125.png 848w, https://substackcdn.com/image/fetch/$s_!9fp5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffd8a98f8-87c5-4711-b5be-e6a23cf7ba38_2000x1125.png 1272w, https://substackcdn.com/image/fetch/$s_!9fp5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffd8a98f8-87c5-4711-b5be-e6a23cf7ba38_2000x1125.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Week 3 (Days 15&#8211;21): Coverage and breadth</strong></p><p>Spend week 3 doing shorter 30-minute drills across 4&#8211;5 archetypes you haven&#8217;t deeply covered. The goal is exposure, not mastery. Knowing the basic shape of an answer for a question you&#8217;re 20% likely to face is much better than having no answer.</p><p>The 30-minute format requires discipline: force yourself to reach the architecture step within 15 minutes. Don&#8217;t let estimation and API design consume your entire drill &#8212; practice moving through the framework efficiently.</p><p>Also in week 3: re-read the estimation numbers cheatsheet and the trade-offs cheatsheet. These apply to every question. Refreshing them mid-prep rather than at the very end gives them time to consolidate.</p><p><strong>Week 4 (Days 22&#8211;28): Two mocks with real feedback</strong></p><p>Stop reading. Stop drilling solo. Do two mock interviews with people who will give you specific, scored feedback.</p><p>The first mock: peer at your target level. Ask them to score you on the 8 dimensions of the take-home rubric. Ask them specifically whether your scoping, communication, and failure mode coverage were strong.</p><p>The second mock: someone above your target level. Their feedback will be harder to hear and more useful. What L6 candidates do that you&#8217;re not doing yet &#8212; that&#8217;s the gap you have four days to close before the interview.</p><p>After each mock: identify the single most impactful change. Spend two days on that one thing. One change made well is more valuable than ten changes made half-heartedly.</p><p><strong>Days 29&#8211;30: Consolidation only</strong></p><p>Day 29: one short drill (30 minutes), no new material. Re-read the framework cheatsheet. That&#8217;s it.</p><p>Day 30 (the day before): re-read the drill card for the archetype most likely to come up at your target company. This takes four minutes. Then stop.</p><p>Don&#8217;t read a new walkthrough the night before. New information the night before competes with everything you&#8217;ve consolidated and doesn&#8217;t have time to integrate. Rest is a legitimate and important part of preparation. Use it.</p><p><strong>What this plan produces</strong></p><p>After thirty days:</p><ul><li><p>Two archetypes with genuine depth and pattern recognition</p></li><li><p>Coverage-level familiarity with four to five additional archetypes</p></li><li><p>Two mocks with documented gaps and one specific improvement made to each</p></li><li><p>The framework cheatsheet and estimation numbers fresh in working memory</p></li></ul><p>You&#8217;ll encounter a question you&#8217;re less prepared for. When that happens, apply the framework. The six-step framework works on questions you haven&#8217;t drilled &#8212; that&#8217;s what it&#8217;s for. The warmup from four weeks of drilling makes the framework run faster and more automatically under pressure.</p><p><strong>The thing most people get wrong</strong></p><p>The ratio of reading to drilling in most engineers&#8217; prep is about 80:20. Reading walkthroughs, reading concept explainers, reading other people&#8217;s summaries.</p><p>The ratio that produces results is closer to 40:60 &#8212; 40% reading and learning, 60% timed drills and mocks. The performance gap between knowing something and producing it under pressure in front of someone is real and only closes with practice under pressure.</p><p>If you have thirty days and you spend twenty-five of them reading, you&#8217;ve done the easy part and skipped the hard part. Do the hard part.</p><div class="callout-block" data-callout="true"><p>The Question Vault has all 52 walkthroughs organized by archetype &#8212; so you can see the pattern across questions, not just the surface answer.</p><p><strong><span>Access all 52 Questions </span><a href="https://systemdrd.com/ebooks/52-faang-questions-drillcards-cheatsheets/">here</a></strong></p></div><div><hr></div><p><strong>CTA:</strong> </p><p>Paid subscribers get one full system design walkthrough </p><p>every Tuesday &#8212; each mapped to its archetype so you build </p><p>pattern recognition, not answer memorization. </p><p>This week: Google Drive / Dropbox.</p><p><a href="https://systemdr.systemdrd.com/subscribe">https://systemdr.systemdrd.com/subscribe</a></p><h2><strong>Subscription link</strong></h2><p><a href="https://systemdr.systemdrd.com/subscribe">https://systemdr.systemdrd.com/subscribe</a></p><p>&#8212;Sumedh</p><p><strong>Want the complete learning path?</strong></p><p>Unlock advanced modules, case studies, and guided exercises.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">System Design Interview Roadmap is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Vector Databases Explained — How Pinecone and Milvus Handle High-Dimensional Data]]></title><description><![CDATA[When Text Search Stops Working]]></description><link>https://systemdr.systemdrd.com/p/vector-databases-explained-how-pinecone</link><guid isPermaLink="false">https://systemdr.systemdrd.com/p/vector-databases-explained-how-pinecone</guid><dc:creator><![CDATA[System Design Roadmap]]></dc:creator><pubDate>Fri, 03 Jul 2026 08:31:09 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!xTJc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90cd94d3-635e-423e-bc13-40bc198f061b_4510x2860.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>When Text Search Stops Working</h2><blockquote><p>Your e-commerce search returns zero results for &#8220;running shoes for bad knees&#8221; because no product title contains that exact phrase. Your document store can&#8217;t surface the policy update most relevant to a user&#8217;s complaint, even though it&#8217;s clearly related. Your recommendation engine has no idea that a user who loves &#8220;Inception&#8221; might enjoy &#8220;Coherence.&#8221;</p></blockquote><blockquote><p>These failures share a root cause: traditional databases index <em>exact values</em>. A B-tree on a VARCHAR column matches &#8220;inception&#8221; or it doesn&#8217;t. It has no concept of <em>semantic proximity</em>. Vector databases exist to close that gap &#8212; storing and querying embeddings so that &#8220;similar meaning&#8221; becomes a first-class query operation.</p></blockquote><div><hr></div><h2>Core Concept: What a Vector Database Actually Does</h2><blockquote><p>An embedding model (BERT, OpenAI&#8217;s <code>text-embedding-3-large</code>, CLIP, etc.) converts your raw data &#8212; text, images, audio &#8212; into a dense float array. A sentence like &#8220;my knee hurts when I run&#8221; becomes a 1,536-dimensional vector. Geometrically, semantically similar things cluster together in that high-dimensional space.</p></blockquote><p>A vector database stores those arrays and answers one primary query: <em>given a query vector Q, return the K nearest stored vectors by some distance metric</em> (cosine similarity, Euclidean distance, or inner product).</p><blockquote><p>The na&#239;ve approach is brute-force: compute the distance between Q and every stored vector. At 100M rows and 1,536 dimensions, that&#8217;s 153.6 billion float operations per query &#8212; too slow for interactive latency.</p></blockquote><p><strong>Approximate Nearest Neighbor (ANN) indexes</strong> trade a small amount of recall for orders-of-magnitude faster lookups. Both Pinecone and Milvus are fundamentally ANN index managers at their core.</p><h3>HNSW: The Dominant Index Structure</h3><p>Hierarchical Navigable Small World graphs are the current standard. Think of it as a multi-layer skip list, but the links between nodes are based on embedding similarity rather than sorted order.</p><ul><li><p><strong>Layer 0</strong> contains all nodes. Higher layers contain exponentially fewer nodes (probabilistic sampling).</p></li><li><p><strong>Insertion</strong> places the vector at the appropriate layers, connecting it to its M nearest neighbors at each layer (M is a tunable parameter &#8212; typically 16&#8211;64).</p></li><li><p><strong>Search</strong> enters at the top layer, greedily hops toward the query vector, then descends to lower layers for progressively finer traversal until Layer 0.</p></li></ul><p>Search complexity is O(log N) in practice. The <code>efConstruction</code> parameter controls how many candidate neighbors are evaluated during index build (quality vs. build speed). The <code>ef</code> parameter at query time controls the dynamic candidate list size (recall vs. latency).</p><p>The non-obvious property: HNSW is not updatable without quality degradation. Deletions mark vectors as &#8220;deleted&#8221; but leave ghost nodes in the graph. After enough deletes, you need to compact &#8212; a full index rebuild.</p><h3>IVF: The Alternative for Memory-Constrained Systems</h3><blockquote><p>Inverted File Index partitions the vector space into K Voronoi cells via k-means clustering. At query time, the search probes the <code>nprobe</code> nearest cluster centroids, then scans only those clusters. This dramatically reduces memory footprint compared to HNSW since you don&#8217;t store full graph adjacency.</p></blockquote><p>Trade-off: if your query vector sits near a cluster boundary, the true nearest neighbor might be in an adjacent unprobed cluster. Recall degrades predictably as <code>nprobe</code> decreases.</p><p><strong>IVF+PQ</strong> (Product Quantization) adds lossy compression of the stored vectors &#8212; splitting each vector into sub-vectors and replacing each with a codebook index. You can compress 1,536-dim float32 vectors (6KB each) to ~192 bytes with minimal recall loss. At 100M vectors, that&#8217;s the difference between 600GB and 19GB of index memory.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xTJc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90cd94d3-635e-423e-bc13-40bc198f061b_4510x2860.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xTJc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90cd94d3-635e-423e-bc13-40bc198f061b_4510x2860.png 424w, https://substackcdn.com/image/fetch/$s_!xTJc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90cd94d3-635e-423e-bc13-40bc198f061b_4510x2860.png 848w, https://substackcdn.com/image/fetch/$s_!xTJc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90cd94d3-635e-423e-bc13-40bc198f061b_4510x2860.png 1272w, https://substackcdn.com/image/fetch/$s_!xTJc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90cd94d3-635e-423e-bc13-40bc198f061b_4510x2860.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xTJc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90cd94d3-635e-423e-bc13-40bc198f061b_4510x2860.png" width="1456" height="923" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/90cd94d3-635e-423e-bc13-40bc198f061b_4510x2860.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:923,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:3012940,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.substack.com/i/191234107?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90cd94d3-635e-423e-bc13-40bc198f061b_4510x2860.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!xTJc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90cd94d3-635e-423e-bc13-40bc198f061b_4510x2860.png 424w, https://substackcdn.com/image/fetch/$s_!xTJc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90cd94d3-635e-423e-bc13-40bc198f061b_4510x2860.png 848w, https://substackcdn.com/image/fetch/$s_!xTJc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90cd94d3-635e-423e-bc13-40bc198f061b_4510x2860.png 1272w, https://substackcdn.com/image/fetch/$s_!xTJc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F90cd94d3-635e-423e-bc13-40bc198f061b_4510x2860.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div>
      <p>
          <a href="https://systemdr.systemdrd.com/p/vector-databases-explained-how-pinecone">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Design Netflix Streaming — The Senior+ Walkthrough]]></title><description><![CDATA[This is the question that defines the streaming media archetype.]]></description><link>https://systemdr.systemdrd.com/p/design-netflix-streaming-the-senior</link><guid isPermaLink="false">https://systemdr.systemdrd.com/p/design-netflix-streaming-the-senior</guid><dc:creator><![CDATA[System Design Roadmap]]></dc:creator><pubDate>Tue, 30 Jun 2026 03:30:15 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/324af9c3-c814-47c5-aa06-d7d6afe30dae_1132x657.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote><p><span>This is the question that defines: </span></p></blockquote><blockquote><p><span>The surface question sounds manageable. Netflix streams video to 270 million subscribers. How hard can it be to store a file and serve it? The probe underneath is what makes this question a senior filter. The interviewer is not testing whether you know what a CDN is. They are testing whether you understand why naive HTTP file serving collapses at scale, what adaptive bitrate encoding is and why it exists, how a CDN edge network makes cold-start latency irrelevant, and what happens when the most-watched show in the world premieres at 9 PM and 50 million people try to start the same episode simultaneously.</span></p></blockquote><p><span>Those four problems &#8212; not the basic architecture &#8212; are where the round is decided.</span></p><p><span>For L4 / mid-level: the content storage and delivery pipeline at a high level. For L5 / senior: adaptive bitrate encoding with multiple renditions, CDN edge caching with pre-positioning, and the cold-start problem. For L6 / staff: the encoding pipeline at scale, multi-region active-active CDN strategy, the playback session architecture, quality-of-experience monitoring, and what Netflix actually does differently from a naive CDN deployment.</span></p><p><span>The Question</span></p><blockquote><p><span>&#8220;Design Netflix. Users should be able to browse a catalog of movies and TV shows and stream them on demand with high quality and low buffering.&#8221;</span></p></blockquote><p><span>Common variants:</span></p><blockquote><p><span>- &#8220;Design YouTube&#8217;s video streaming system.&#8221;</span></p><p><span>- &#8220;Design Spotify&#8217;s audio streaming.&#8221;</span></p><p><span>- &#8220;Design Twitch&#8217;s live streaming platform.&#8221;</span></p><p><span>- &#8220;Design an adaptive bitrate streaming system.&#8221;</span></p><p><span>- &#8220;Design the video encoding pipeline for a platform like Netflix.&#8221;</span></p></blockquote><p><span>The first two are nearly identical to Netflix. Twitch adds a real-time constraint (live, not on-demand) that changes the delivery model but not the encoding fundamentals. Spotify replaces video with audio &#8212; smaller files, same adaptive delivery architecture. The encoding pipeline variant focuses specifically on Phase 2 below.</span></p><h3><span>Step 1 &#8212; Clarify Before You Draw</span></h3><p><span>Six questions. The first three are load-bearing.</span></p><p><strong><span>1. On-demand only, or also live streaming? </span></strong><span>On-demand (Netflix, Spotify) and live (Twitch, live sports) have meaningfully different architectures. On-demand content can be pre-encoded, pre-cached at CDN edges, and optimized offline. Live content has a latency requirement (viewers want near-real-time) that forces a different delivery model. Clarify and scope to on-demand unless told otherwise.</span></p><p><strong><span>2. What devices must be supported? </span></strong><span>Smart TVs, mobile (iOS/Android), web browsers, game consoles. This matters because different devices support different codecs (H.264, H.265/HEVC, AV1, VP9) and different DRM systems (Widevine, FairPlay, PlayReady). Acknowledge the codec diversity; don&#8217;t try to design the full DRM system in the interview &#8212; it&#8217;s a separate subsystem.</span></p><p><strong><span>3. What are the quality and latency SLOs? </span></strong><span>Netflix targets: playback starts within 2 seconds of pressing play. Buffering events under 0.5% of total play time. 4K HDR delivery available on supported devices. These numbers drive every architecture decision &#8212; state them explicitly before drawing anything.</span></p><p><strong><span>4. What is the catalog size? </span></strong><span>Netflix has approximately 36,000 titles globally (varies by region). Each title is stored in multiple renditions and formats. State the working assumption: 36,000 titles &#215; 20 renditions &#215; ~4 GB per rendition = ~3 PB of encoded video. This estimate calibrates the storage and CDN design.</span></p><p><strong><span>5. What scale? </span></strong><span>270 million subscribers. Peak concurrent streams: approximately 15&#8211;20% of active users simultaneously &#8212; roughly 40&#8211;50 million concurrent streams. At peak (new season premiere, weekend evening), this spikes significantly. State the peak assumption explicitly.</span></p><p><strong><span>6. Does the design include recommendations, search, and the catalog UI? </span></strong><span>These are separate systems (ML recommendation engine, search index, catalog metadata API). Acknowledge they exist; scope the interview to the streaming pipeline &#8212; content ingestion, encoding, storage, and delivery. Otherwise you&#8217;ll spend 30 minutes on recommendation and never get to the hard part.</span></p><h3><span>Step 2 &#8212; Estimate</span></h3><p><span>Working assumptions:</span></p><blockquote><p><span>- 36,000 titles &#215; 20 renditions per title = 720,000 encoded files</span></p><p><span>- Average rendition size: 4 GB (HD, 2-hour movie)</span></p><p><span>- Total encoded storage: 720,000 &#215; 4 GB &#8776; </span><strong><span>3 PB </span></strong><span>of video content</span></p><p><span>- Metadata storage (titles, posters, descriptions, subtitles): ~5 TB &#8212; trivial by comparison - Peak concurrent streams: 50 million</span></p><p><span>- Average bitrate served: 5 Mbps (mix of HD and 4K streams)</span></p><p><span>- Peak egress bandwidth: 50M streams &#215; 5 Mbps = </span><strong><span>250 Tbps</span></strong></p></blockquote><p><span>That 250 Tbps peak egress number is the most important figure in the whole estimate. Netflix is one of the largest sources of internet traffic on the planet &#8212; at peak, it accounts for roughly 15% of global downstream internet bandwidth. No single origin infrastructure serves this. CDN edge servers distributed globally are the only viable answer. State this conclusion explicitly from the estimate.</span></p><p><span>Content ingestion rate: Netflix adds roughly 500&#8211;1,000 hours of new content per month. At 20 renditions per title, that&#8217;s ~10,000&#8211;20,000 encoding jobs per month &#8212; a background batch process, not a latency-sensitive path.</span></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe&quot;,&quot;text&quot;:&quot;Get Access to GitHub Repo&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://systemdr.systemdrd.com/subscribe"><span>Get Access to GitHub Repo</span></a></p><h3><span>Step 3 &#8212; API Design</span></h3><p><span>Four APIs. The streaming API is the non-obvious one.</span></p><div class="callout-block" data-callout="true"><p><span>GET /v1/catalog</span></p><p><span>Query: page_token, limit, genre?, region</span></p><p><span>Response: { titles: [...], next_page_token }</span></p><p><span>Note: region-filtered &#8212; different catalogs per country (licensing)</span></p><p><span>GET /v1/titles/:title_id</span></p><p><span>Response: {</span></p><p><span>title_id, name, description, genres, cast,</span></p><p><span>available_resolutions: [&#8221;4K&#8221;, &#8220;1080p&#8221;, &#8220;720p&#8221;, &#8220;480p&#8221;],</span></p><p><span>subtitles: [{ language, url }],</span></p><p><span>poster_url, trailer_url</span></p><p><span>}</span></p><p><span>POST /v1/playback/start</span></p><p><span>Body: {</span></p><p><span>title_id: string,</span></p><p><span>content_id: string, (specific episode or movie version)</span></p><p><span>device_type: string,</span></p><p><span>supported_codecs: [&#8221;H264&#8221;, &#8220;H265&#8221;, &#8220;AV1&#8221;],</span></p><p><span>network_speed_mbps: float, &#8592; client measures and reports</span></p><p><span>drm_system: &#8220;widevine&#8221; | &#8220;fairplay&#8221; | &#8220;playready&#8221;,</span></p><p><span>resume_position_seconds: integer</span></p><p><span>}</span></p><p><span>Response: {</span></p><p><span>session_id: string,</span></p><p><span>manifest_url: string, &#8592; THE KEY RESPONSE FIELD</span></p><p><span>license_token: string, (for DRM decryption)</span></p><p><span>cdn_edge_url: string,</span></p><p><span>initial_quality: &#8220;1080p&#8221;,</span></p><p><span>heartbeat_interval_seconds: 30</span></p><p><span>}</span></p><p><span>POST /v1/playback/heartbeat</span></p><p><span>Body: {</span></p><p><span>session_id: string,</span></p><p><span>position_seconds: integer,</span></p><p><span>current_quality: string,</span></p><p><span>buffer_health_seconds:</span></p><p><span>float,</span></p><p><span>rebuffer_events: integer,</span></p><p><span>bandwidth_estimate_mbps: float</span></p><p><span>}</span></p><p><span>Response: { continue: true, quality_recommendation: &#8220;720p&#8221; }</span></p></div><p><strong><span>The senior move here: </span></strong><span>The </span><span data-color="rgb(24, 128, 56)" style="color: rgb(24, 128, 56);">manifest_url </span><span>in the playback start response is the key design signal. You are not returning a video file URL &#8212; you are returning a manifest file URL. This distinction is the entire adaptive bitrate streaming architecture. Explain it before moving on.</span></p><p><strong><span>The </span><span data-color="rgb(24, 128, 56)" style="color: rgb(24, 128, 56);">heartbeat </span><span>endpoint </span></strong><span>is the second senior signal. Netflix does not stream and forget. Every 30 seconds, the player reports back: current position, current quality, buffer health, rebuffer events, estimated bandwidth. This telemetry is the basis for quality-of-experience monitoring, A/B testing new streaming algorithms, and detecting degraded CDN nodes before users notice. Candidates who include the heartbeat signal they&#8217;ve thought about the operational layer, not just the happy path.</span></p><h3><span>Step 4 &#8212; Data Model</span></h3><p><span>Five stores. Video content itself is not in any of these &#8212; it lives in object storage.</span></p><p><span data-color="rgb(24, 128, 56)" style="color: rgb(24, 128, 56);">titles </span><span data-color="rgb(67, 67, 67)" style="color: rgb(67, 67, 67);">table &#8212; catalog metadata</span></p><p><span>title_id, title, description, genres[], cast[], director,</span></p><p><span>release_year, rating, available_regions[], duration_seconds,</span></p><p><span>thumbnail_url, created_at, updated_at</span></p><p><span>Sharded by </span><span data-color="rgb(24, 128, 56)" style="color: rgb(24, 128, 56);">title_id</span><span>. Regional availability (</span><span data-color="rgb(24, 128, 56)" style="color: rgb(24, 128, 56);">available_regions[]</span><span>) drives catalog filtering &#8212; a subscriber in Germany sees a different catalog than one in the US because Netflix licenses content per territory.</span></p><p><span data-color="rgb(24, 128, 56)" style="color: rgb(24, 128, 56);">content_assets </span><span data-color="rgb(67, 67, 67)" style="color: rgb(67, 67, 67);">table &#8212; encoded renditions index</span></p><p><span>content_id, title_id, rendition_type (4K/1080p/720p/480p/360p),</span></p><p><span>codec (H264/H265/AV1), bitrate_kbps, file_size_bytes,</span></p><p><span>storage_uri (S3 path), manifest_uri, duration_seconds,</span></p><p><span>encoding_status (pending/processing/ready), created_at</span></p><p style="text-align: justify;"><span>The </span><span data-color="rgb(24, 128, 56)" style="color: rgb(24, 128, 56);">manifest_uri </span><span>points to the HLS or DASH manifest file in S3 &#8212; the index of all segments for this rendition. When the player starts playback, it downloads the manifest first, then requests individual segments.</span></p><p><span data-color="rgb(24, 128, 56)" style="color: rgb(24, 128, 56);">playback_sessions </span><span data-color="rgb(67, 67, 67)" style="color: rgb(67, 67, 67);">table &#8212; active and recent sessions </span><span>session_id, user_id, content_id, device_type, started_at,</span></p><p><span>last_heartbeat_at, current_position_seconds, current_quality,</span></p><p><span>total_play_time_seconds, rebuffer_count, total_rebuffer_seconds</span></p><p><span>Not stored in your OLTP database. High-frequency writes (heartbeat every 30 seconds, 50M concurrent sessions = ~1.7M writes/sec). Use Cassandra or a time-series store. Partition by </span><span data-color="rgb(24, 128, 56)" style="color: rgb(24, 128, 56);">user_id </span><span>so &#8220;resume where I left off&#8221; is a single-partition read. Short TTL &#8212; you only need the last 30 days of session data for analytics; older data goes to cold storage.</span></p><p><span data-color="rgb(24, 128, 56)" style="color: rgb(24, 128, 56);">user_watch_history </span><span data-color="rgb(67, 67, 67)" style="color: rgb(67, 67, 67);">&#8212; resume position and completion </span><span>user_id, title_id, content_id, position_seconds, completed (boolean), watched_at, device_type</span></p><p><span>This is what powers &#8220;continue watching.&#8221; Separate from the playback session &#8212; a session is live, watch history is the permanent record. Partition by </span><span data-color="rgb(24, 128, 56)" style="color: rgb(24, 128, 56);">user_id</span><span>.</span></p><p><span data-color="rgb(67, 67, 67)" style="color: rgb(67, 67, 67);">CDN content index &#8212; not a database table</span></p><p><span>The CDN&#8217;s internal index of what content is cached at which edge location. You don&#8217;t design this &#8212; it&#8217;s the CDN&#8217;s internal state. What you do design is the </span><strong><span>pre-positioning logic</span></strong><span>: before a major content release (new season of a hit show), Netflix pre-pushes the encoded files to CDN edge servers before playback demand arrives. This is called </span><strong><span>content pre-warming </span></strong><span>and it is one of the most important operational patterns in the whole system.</span></p><div class="callout-block" data-callout="true"><p><span data-color="rgb(54, 55, 55)" style="color: rgb(54, 55, 55);">Preparing for a distributed systems interview?</span><br><span data-color="rgb(54, 55, 55)" style="color: rgb(54, 55, 55);">&#8594;</span><a href="https://systemdrd.com/ebooks/sdcourse-distributed-systems-interview">Download the free Interview Pack</a><br><span data-color="rgb(54, 55, 55)" style="color: rgb(54, 55, 55);">&#8594; </span><a href="https://systemdr.systemdrd.com/subscribe">Subscribe</a><span data-color="rgb(54, 55, 55)" style="color: rgb(54, 55, 55);"> now to access source code repository - 200 + coding lessons</span></p></div>
      <p>
          <a href="https://systemdr.systemdrd.com/p/design-netflix-streaming-the-senior">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[CAP Theorem: What It Actually Means in an Interview]]></title><description><![CDATA[CAP theorem is one of the most cited concepts in system design interviews and one of the most consistently misapplied.]]></description><link>https://systemdr.systemdrd.com/p/cap-theorem-what-it-actually-means</link><guid isPermaLink="false">https://systemdr.systemdrd.com/p/cap-theorem-what-it-actually-means</guid><dc:creator><![CDATA[System Design Roadmap]]></dc:creator><pubDate>Sun, 28 Jun 2026 03:30:29 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!BCp6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0e9faf1-9cfd-4567-bff5-384ec310be38_4675x2750.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>CAP theorem is one of the most cited concepts in system design interviews and one of the most consistently misapplied.</p><p>The standard failure mode: a candidate mentions CAP theorem as a vocabulary signal (&#8221;we need to think about the CAP trade-off here&#8221;), states the three letters (Consistency, Availability, Partition tolerance), and moves on without connecting it to a concrete decision.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">System Design Interview Roadmap is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>The interviewer writes &#8220;mentioned CAP but couldn&#8217;t apply it.&#8221; The round continues.</p><p>Here&#8217;s what applying it actually looks like.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!BCp6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0e9faf1-9cfd-4567-bff5-384ec310be38_4675x2750.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!BCp6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0e9faf1-9cfd-4567-bff5-384ec310be38_4675x2750.png 424w, https://substackcdn.com/image/fetch/$s_!BCp6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0e9faf1-9cfd-4567-bff5-384ec310be38_4675x2750.png 848w, https://substackcdn.com/image/fetch/$s_!BCp6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0e9faf1-9cfd-4567-bff5-384ec310be38_4675x2750.png 1272w, https://substackcdn.com/image/fetch/$s_!BCp6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0e9faf1-9cfd-4567-bff5-384ec310be38_4675x2750.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!BCp6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0e9faf1-9cfd-4567-bff5-384ec310be38_4675x2750.png" width="1456" height="856" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f0e9faf1-9cfd-4567-bff5-384ec310be38_4675x2750.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:856,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:779742,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://systemdr.systemdrd.com/i/198937089?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0e9faf1-9cfd-4567-bff5-384ec310be38_4675x2750.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!BCp6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0e9faf1-9cfd-4567-bff5-384ec310be38_4675x2750.png 424w, https://substackcdn.com/image/fetch/$s_!BCp6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0e9faf1-9cfd-4567-bff5-384ec310be38_4675x2750.png 848w, https://substackcdn.com/image/fetch/$s_!BCp6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0e9faf1-9cfd-4567-bff5-384ec310be38_4675x2750.png 1272w, https://substackcdn.com/image/fetch/$s_!BCp6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff0e9faf1-9cfd-4567-bff5-384ec310be38_4675x2750.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>What CAP actually says</strong></p><p>CAP theorem says: in the presence of a network partition &#8212; when some nodes in your distributed system can&#8217;t communicate with others &#8212; you must choose between consistency and availability. You cannot have both.</p><p><em>Consistency</em> here means: every read returns the most recent write, or an error. Every node agrees on the current state.</p><p><em>Availability</em> means: every request gets a response. It may not be the most recent data, but the system doesn&#8217;t error or time out.</p><p><em>Partition tolerance</em> isn&#8217;t a choice &#8212; it&#8217;s a given. If you&#8217;re building a distributed system that runs over a real network, partitions happen. Network cables fail. Datacenters lose connectivity. You cannot opt out of partition tolerance. The real choice is always: when a partition happens, do you stay consistent or available?</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe&quot;,&quot;text&quot;:&quot;Subscribe for Payments Walkthrough&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://systemdr.systemdrd.com/subscribe"><span>Subscribe for Payments Walkthrough</span></a></p><p><strong>Where it actually matters</strong></p><p>The question is rarely &#8220;should I build a CP or AP system?&#8221; That&#8217;s too abstract to be useful. The useful version is: for <em>this specific read</em>, how stale can the data be before it causes a real problem?</p><p>Some reads tolerate stale data completely. Your Twitter follower count being one minute stale costs nothing. Your Netflix streaming recommendation being 24 hours stale costs nothing. These are candidates for eventual consistency &#8212; replicate async, serve locally, accept a brief window of inconsistency.</p><p>Some reads cannot tolerate stale data. Your bank account balance must be accurate before a payment is authorized. Your ticket reservation must be current before a seat is sold. These require strong consistency &#8212; at the cost of higher latency and potential availability loss during a partition.</p><p>The L5 answer isn&#8217;t &#8220;I&#8217;ll use eventual consistency.&#8221; It&#8217;s: &#8220;For the timeline read, I&#8217;ll accept eventual consistency &#8212; a post appearing 30 seconds late costs nothing. For the payment authorization, I need strong consistency &#8212; an incorrect balance check is a real financial loss. These two paths use different consistency models within the same system.&#8221;</p><p><strong>PACELC: the extension worth knowing</strong></p><p>CAP only talks about partition scenarios. PACELC extends the model to the normal case: even without a partition, there&#8217;s a trade-off between latency and consistency. If you want every read to reflect the latest write, you need to coordinate across replicas &#8212; which adds latency. If you serve from the nearest replica without coordination, you have lower latency but possible stale reads.</p><p>Knowing PACELC by name is a mild L6 signal. More importantly, understanding that the consistency/latency trade-off exists even on sunny days is what matters.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ufc7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9801ff2-eb55-43be-a9d1-86c9c5ad7a82_4950x2860.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ufc7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9801ff2-eb55-43be-a9d1-86c9c5ad7a82_4950x2860.png 424w, https://substackcdn.com/image/fetch/$s_!Ufc7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9801ff2-eb55-43be-a9d1-86c9c5ad7a82_4950x2860.png 848w, https://substackcdn.com/image/fetch/$s_!Ufc7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9801ff2-eb55-43be-a9d1-86c9c5ad7a82_4950x2860.png 1272w, https://substackcdn.com/image/fetch/$s_!Ufc7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9801ff2-eb55-43be-a9d1-86c9c5ad7a82_4950x2860.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ufc7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9801ff2-eb55-43be-a9d1-86c9c5ad7a82_4950x2860.png" width="1456" height="841" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e9801ff2-eb55-43be-a9d1-86c9c5ad7a82_4950x2860.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:841,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:958688,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.systemdrd.com/i/198937089?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9801ff2-eb55-43be-a9d1-86c9c5ad7a82_4950x2860.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Ufc7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9801ff2-eb55-43be-a9d1-86c9c5ad7a82_4950x2860.png 424w, https://substackcdn.com/image/fetch/$s_!Ufc7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9801ff2-eb55-43be-a9d1-86c9c5ad7a82_4950x2860.png 848w, https://substackcdn.com/image/fetch/$s_!Ufc7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9801ff2-eb55-43be-a9d1-86c9c5ad7a82_4950x2860.png 1272w, https://substackcdn.com/image/fetch/$s_!Ufc7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9801ff2-eb55-43be-a9d1-86c9c5ad7a82_4950x2860.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>The three decisions CAP drives in practice</strong></p><p>When you reach the data model step in a design interview, CAP should inform exactly three things:</p><p><em>Replication strategy.</em> Synchronous replication (every write waits for all replicas to confirm) gives strong consistency at the cost of write latency. Asynchronous replication (write confirms when the leader writes, replicas catch up later) gives lower write latency but a brief consistency window.</p><p><em>Read routing.</em> If you route reads to the leader only, you always get the latest data. If you route reads to any replica, you get lower latency but potentially stale data. Pick based on what each read is for.</p><p><em>Conflict resolution.</em> When two nodes accept writes for the same key during a partition, you have a conflict. Last-writer-wins, vector clocks, CRDTs, operational transforms &#8212; each is a different answer to the same CAP-induced conflict problem.</p><p>The engineers who use CAP well in interviews don&#8217;t mention it as a signal. They use it as a decision tool. &#8220;For the payment authorization read, I need consistency over availability &#8212; I&#8217;ll route to the leader and accept higher latency.&#8221; That sentence is CAP applied correctly. It doesn&#8217;t require saying &#8220;CAP&#8221; at all.</p><div><hr></div><p><strong>CTA:</strong> The Stripe Payments walkthrough (paid post #2) covers the consistency decisions in a payment system end-to-end &#8212; exactly where strong consistency is required, exactly where eventual is acceptable, and why.</p><h2><strong>Subscription link</strong></h2><p><a href="https://systemdr.systemdrd.com/subscribe">https://systemdr.systemdrd.com/subscribe</a></p><p>&#8212;Sumedh</p><div class="callout-block" data-callout="true"><p>The Question Vault has all 52 walkthroughs organized by archetype &#8212; so you can see the pattern across questions, not just the surface answer.</p><p><strong>Access all 52 Quesstions <a href="https://systemdrd.com/ebooks/52-faang-questions-drillcards-cheatsheets/">here</a></strong></p></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">System Design Interview Roadmap is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[The “Split-Brain” Resolver: Automated Recovery Strategies for Partitioned Clusters]]></title><description><![CDATA[Section 8 &#8212; Article 214 | Production Engineering & Optimization]]></description><link>https://systemdr.systemdrd.com/p/the-split-brain-resolver-automated</link><guid isPermaLink="false">https://systemdr.systemdrd.com/p/the-split-brain-resolver-automated</guid><dc:creator><![CDATA[System Design Roadmap]]></dc:creator><pubDate>Fri, 26 Jun 2026 08:30:35 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!0eWC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc56ea41b-be24-47ca-a12d-32d76a21c0e1_3375x2325.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2><blockquote><p>Your three-node Elasticsearch cluster just survived a network blip. Thirty seconds of packet loss between your primary datacenter and a secondary AZ. When connectivity restored, you discovered two nodes had independently accepted writes during the partition. Both believe they are the authoritative master. Both have diverged. This is split-brain &#8212; and the next 60 seconds will determine whether your data converges gracefully or you spend the next six hours manually reconciling indexes.</p></blockquote><div><hr></div><h2>What Split-Brain Actually Is</h2><p>Split-brain occurs when a distributed cluster partitions into two or more segments that each achieve quorum independently, or when quorum rules are misconfigured to allow it. Each segment continues operating as if it were the whole cluster. Writes flow into both sides. Neither segment knows it is operating on a stale view of the world.</p><p>The core problem is <em>divergent state</em>: two leaders, two write paths, two versions of truth. When the partition heals, the cluster must decide which side&#8217;s state wins &#8212; or whether a merge is even possible.</p><p><strong>Why quorum isn&#8217;t always enough.</strong> Strict majority quorum (N/2 + 1 nodes required) prevents split-brain in theory. In practice, operators often lower quorum thresholds under operational pressure (&#8221;we only have 2 of 3 nodes, let&#8217;s keep serving&#8221;), or they run even-numbered clusters, or they misconfigure <code>minimum_master_nodes</code> (Elasticsearch&#8217;s historical footgun). The gap between theoretical safety and deployed reality is where split-brain lives.</p><p><strong>Three failure modes:</strong></p><ol><li><p><strong>Network partition with symmetric quorum loss</strong> &#8212; a 2-node cluster loses its tiebreaker. Both nodes independently promote themselves.</p></li><li><p><strong>GC pause masquerading as a failure</strong> &#8212; a node pauses for 8 seconds (JVM GC, system call blocking), the cluster assumes it&#8217;s dead and elects a replacement, then the original node wakes up believing it still holds the lease.</p></li><li><p><strong>Asymmetric network failures</strong> &#8212; Node A can reach Node B, Node B can reach Node C, but A cannot reach C. Quorum calculations become topology-dependent.</p></li></ol><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0eWC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc56ea41b-be24-47ca-a12d-32d76a21c0e1_3375x2325.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0eWC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc56ea41b-be24-47ca-a12d-32d76a21c0e1_3375x2325.png 424w, https://substackcdn.com/image/fetch/$s_!0eWC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc56ea41b-be24-47ca-a12d-32d76a21c0e1_3375x2325.png 848w, https://substackcdn.com/image/fetch/$s_!0eWC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc56ea41b-be24-47ca-a12d-32d76a21c0e1_3375x2325.png 1272w, https://substackcdn.com/image/fetch/$s_!0eWC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc56ea41b-be24-47ca-a12d-32d76a21c0e1_3375x2325.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0eWC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc56ea41b-be24-47ca-a12d-32d76a21c0e1_3375x2325.png" width="1456" height="1003" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c56ea41b-be24-47ca-a12d-32d76a21c0e1_3375x2325.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1003,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1031614,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.substack.com/i/191234067?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc56ea41b-be24-47ca-a12d-32d76a21c0e1_3375x2325.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!0eWC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc56ea41b-be24-47ca-a12d-32d76a21c0e1_3375x2325.png 424w, https://substackcdn.com/image/fetch/$s_!0eWC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc56ea41b-be24-47ca-a12d-32d76a21c0e1_3375x2325.png 848w, https://substackcdn.com/image/fetch/$s_!0eWC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc56ea41b-be24-47ca-a12d-32d76a21c0e1_3375x2325.png 1272w, https://substackcdn.com/image/fetch/$s_!0eWC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc56ea41b-be24-47ca-a12d-32d76a21c0e1_3375x2325.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p>
      <p>
          <a href="https://systemdr.systemdrd.com/p/the-split-brain-resolver-automated">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Design WhatsApp — The Senior+ Walkthrough]]></title><description><![CDATA[This is the question that defines the real-time messaging archetype.]]></description><link>https://systemdr.systemdrd.com/p/design-whatsapp-the-senior-walkthrough</link><guid isPermaLink="false">https://systemdr.systemdrd.com/p/design-whatsapp-the-senior-walkthrough</guid><dc:creator><![CDATA[System Design Roadmap]]></dc:creator><pubDate>Tue, 23 Jun 2026 03:31:02 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!WJKt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8dea1b8-ed5c-460e-8728-796ec0b725f8_2048x1240.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote><p>This is the question that defines the real-time messaging archetype. Ten questions in the question bank are variants of it &#8212; Slack, Discord, Zoom, Twitter Spaces, iMessage, Facebook Messenger, Google Chat. They share a spine: a long-lived connection problem, a delivery semantics problem, and a presence problem. Get fluent with all three and you can answer any messaging interview you&#8217;re handed.</p></blockquote><blockquote><p>The surface question looks simple: two people want to send each other messages. The probe underneath is anything but. Interviewers use this question because it exposes how candidates think about distributed systems under failure &#8212; specifically what happens when the recipient is offline, when the network drops mid-message, when the same message arrives twice, and when a user has five devices. Those four failure modes, and your response to them, are where the round is decided.</p></blockquote><blockquote><p>For L4 / mid-level: the basic chat flow and message storage. For L5 / senior: delivery semantics under unreliable networks (at-most-once, at-least-once, exactly-once), presence at scale, and offline message handling. For L6 / staff: the multi-device consistency model, group message fan-out at WhatsApp&#8217;s scale (2 billion users), end-to-end encryption architecture, and what happens when a message is delivered to 256 group members across 12 time zones while half of them are offline.</p></blockquote><div><hr></div><h2>The Question</h2><blockquote><p>&#8220;Design WhatsApp. Users should be able to send messages to each other in real time. Messages should be delivered even when the recipient is temporarily offline.&#8221;</p></blockquote><p>Common variants:</p><ul><li><p>&#8220;Design Facebook Messenger.&#8221;</p></li><li><p>&#8220;Design iMessage / Apple Messages.&#8221;</p></li><li><p>&#8220;Design Slack&#8217;s messaging core.&#8221;</p></li><li><p>&#8220;Design a real-time chat system.&#8221;</p></li><li><p>&#8220;Design the messaging layer for [our product].&#8221;</p></li></ul><p>All five are the same architecture. Slack adds channels and threads; the delivery model is identical. iMessage adds end-to-end encryption; the transport is identical. Discord adds voice and server-based channels; the one-to-one messaging core is identical.</p><div><hr></div><h2>Step 1 &#8212; Clarify Before You Draw</h2><p>Six questions. Two of them are load-bearing for the entire design.</p><p><strong>1. One-to-one only, or also group chats?</strong> One-to-one is the simpler problem. Group chats add fan-out &#8212; sending one message to N recipients &#8212; which at WhatsApp&#8217;s scale means up to 256 recipients per group. State which you&#8217;re designing for. For L5+: design for both, but start with one-to-one and explicitly extend.</p><p><strong>2. What are the delivery guarantees?</strong> This is the load-bearing question. Three options:</p><ul><li><p><em>At-most-once:</em> messages might be lost but never duplicated. Fine for ephemeral signals (typing indicators). Terrible for chat.</p></li><li><p><em>At-least-once:</em> messages are definitely delivered but might be delivered more than once. The receiver handles deduplication. Acceptable for most chat systems.</p></li><li><p><em>Exactly-once:</em> messages are delivered exactly once, regardless of retries. Theoretically ideal. In practice, you can approximate it with idempotency keys and deduplication at the receiver &#8212; but you cannot achieve it perfectly across an unreliable network. Saying &#8220;exactly-once is impossible in a distributed system&#8221; out loud is a senior signal.</p></li></ul><p>WhatsApp and most production systems implement at-least-once delivery with client-side deduplication. State this explicitly.</p><p><strong>3. What devices does each user have?</strong> Multiple devices per user (phone, tablet, web, desktop) massively complicates the model. A message sent to a user needs to land on all their active devices. On which device does the &#8220;read receipt&#8221; trigger? Clarify this early.</p><p><strong>4. Offline handling &#8212; how long do you store messages for an offline recipient?</strong> If a recipient is offline for 30 days, do their messages accumulate on your servers? Most production systems store for 30 days and drop after that (with notification to sender). Clarify the retention window.</p><p><strong>5. End-to-end encryption?</strong> E2EE (like WhatsApp&#8217;s Signal Protocol implementation) means the server cannot read message content &#8212; it only stores encrypted ciphertext and routing metadata. This changes the data model significantly. State whether you&#8217;re designing with E2EE or not. For L5: acknowledge it exists and where it fits. For L6+: explain the key exchange flow.</p><p><strong>6. What scale?</strong> 2 billion monthly active users is WhatsApp&#8217;s actual scale. For the interview, pick a working number: 500M DAU, 100 billion messages per day (WhatsApp&#8217;s reported figure as of its scale). These numbers drive your storage and throughput estimates.</p><div><hr></div><h2>Step 2 &#8212; Estimate</h2><p>Working assumptions:</p><ul><li><p>500M daily active users</p></li><li><p>100 billion messages per day = ~1.16 million messages per second average, ~5M/sec peak</p></li><li><p>Average message size: 100 bytes (text only), 500 bytes with metadata</p></li><li><p>30-day message retention for offline recipients</p></li><li><p>1 billion messages stored at any moment (roughly 1% of daily volume is &#8220;pending delivery&#8221;)</p></li><li><p>Media (images, video, voice): handle separately via object storage (S3 / CDN pre-signed URLs); only metadata and a pointer lives in the chat system</p></li></ul><p>Storage for messages: 100B messages/day &#215; 500 bytes &#215; 30 days retention &#8776; 1.5 PB. This is your &#8220;hot&#8221; storage &#8212; messages waiting to be delivered or recently delivered. After 30 days, messages drop off the hot store. Delivered messages can be stored client-side and expunged from the server (this is exactly what WhatsApp does &#8212; server deletes after delivery confirmation).</p><p>Connection state: 500M users &#215; ~30% concurrently connected = ~150M concurrent WebSocket connections. At 64KB per connection socket buffer that&#8217;s roughly 9.6 TB of connection memory across your fleet. This is one of the hardest scaling problems in messaging &#8212; the number of open connections.</p><p>Write throughput: 1.16M messages/sec average into a message store. This rules out single-node anything. You need a distributed message queue and a sharded persistence layer.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe&quot;,&quot;text&quot;:&quot;Get Access to GitHub Repo&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://systemdr.systemdrd.com/subscribe"><span>Get Access to GitHub Repo</span></a></p><div><hr></div><h2>Step 3 &#8212; API Design</h2><p>Four endpoints. The real-time delivery is not REST &#8212; it&#8217;s a persistent connection.</p><p>WebSocket: wss://chat.whatsapp.com/connect</p><p>Auth:    Bearer token in Upgrade request headers</p><p>Purpose: The long-lived connection for receiving messages and sending keep-alives. All message delivery happens here.</p><p>On connect: server sends any pending (undelivered) messages accumulated while the client was offline.</p><div class="callout-block" data-callout="true"><p>POST /v1/messages/send</p><p>  Idempotency-Key: &lt;client-generated UUID&gt;     &#8592; THE PROBE</p><p>  Body: {</p><p>    to_user_id: string,</p><p>    message_id: string,        (client-generated, for dedup)</p><p>    content_encrypted: bytes,  (ciphertext if E2EE)</p><p>    content_type: &#8220;text&#8221; | &#8220;image&#8221; | &#8220;audio&#8221; | &#8220;video&#8221;,</p><p>    media_url: string,         (pre-uploaded, optional)</p><p>    client_timestamp: epoch_ms</p><p>  }</p><p>  Response: {</p><p>    message_id: string,</p><p>    server_timestamp: epoch_ms,</p><p>    status: &#8220;queued&#8221; | &#8220;delivered&#8221;</p><p>  }</p><p>POST /v1/messages/ack</p><p>  Body: { message_id: string, ack_type: &#8220;delivered&#8221; | &#8220;read&#8221; }</p><p>  Purpose: Explicit delivery and read acknowledgment from client.</p><p>           Server relays read receipts back to sender.</p><p>GET /v1/users/:user_id/presence</p><p>  Response: { status: &#8220;online&#8221; | &#8220;offline&#8221; | &#8220;last_seen_at&#8221;: timestamp }</p><p>  Note: WhatsApp makes presence opt-out &#8212; users can hide last seen.</p><p>        This is a privacy setting, not a system constraint.</p></div><p><strong>The senior move on the API step:</strong> Name the Idempotency-Key and message_id in the same breath. The message_id is client-generated before the send &#8212; if the client retries because it didn&#8217;t receive an ack, the server detects the duplicate via message_id and does not re-queue. The Idempotency-Key is the HTTP-level dedup. Both are necessary: the HTTP key handles transport-level retries, the message_id handles application-level deduplication across devices and reconnections.</p><p>Saying that distinction out loud &#8212; <em>two levels of deduplication for two different failure modes</em> &#8212; is the L6 signal on this question.</p><div class="callout-block" data-callout="true"><p><a href="https://systemdr.systemdrd.com/subscribe">Subscribe</a> now to <br>&#8594;unlock complete system design walkthroughs<br>&#8594; Get access to downloadable Drill Cards and full walkthrough</p></div>
      <p>
          <a href="https://systemdr.systemdrd.com/p/design-whatsapp-the-senior-walkthrough">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[The Scoping Discipline — Why Engineers Design Too Much]]></title><description><![CDATA[Learn System Design with System building, Subscribe Hands On coding course - LogStream]]></description><link>https://systemdr.systemdrd.com/p/the-scoping-discipline</link><guid isPermaLink="false">https://systemdr.systemdrd.com/p/the-scoping-discipline</guid><dc:creator><![CDATA[System Design Roadmap]]></dc:creator><pubDate>Sun, 21 Jun 2026 03:30:34 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!ife-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7371b8-858e-4ccf-ba1a-8cfdfe2246dc_4950x2640.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="callout-block" data-callout="true"><p>Learn <strong>System Design with System building, Subscribe Hands On coding course - <a href="https://sdcourse.substack.com/p/start-here-how-to-use-sdcourse">LogStream</a></strong></p></div><p>There&#8217;s a version of the system design interview where the candidate designs Twitter. The entire Twitter. Timeline, search, notifications, recommendations, ads, analytics, direct messages.</p><p>At the 40-minute mark they&#8217;re still drawing boxes. They haven&#8217;t gone deep on anything. The interviewer writes &#8220;breadth over depth, no clear prioritization&#8221; on the scorecard.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">System Design Interview Roadmap is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>This is the most common failure mode among technically strong candidates, and it has nothing to do with technical knowledge. It&#8217;s a scoping problem.</p><p>Here&#8217;s the discipline that fixes it.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ife-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7371b8-858e-4ccf-ba1a-8cfdfe2246dc_4950x2640.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ife-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7371b8-858e-4ccf-ba1a-8cfdfe2246dc_4950x2640.png 424w, https://substackcdn.com/image/fetch/$s_!ife-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7371b8-858e-4ccf-ba1a-8cfdfe2246dc_4950x2640.png 848w, https://substackcdn.com/image/fetch/$s_!ife-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7371b8-858e-4ccf-ba1a-8cfdfe2246dc_4950x2640.png 1272w, https://substackcdn.com/image/fetch/$s_!ife-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7371b8-858e-4ccf-ba1a-8cfdfe2246dc_4950x2640.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ife-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7371b8-858e-4ccf-ba1a-8cfdfe2246dc_4950x2640.png" width="1456" height="777" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fe7371b8-858e-4ccf-ba1a-8cfdfe2246dc_4950x2640.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:777,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:708052,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://systemdr.systemdrd.com/i/198936747?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7371b8-858e-4ccf-ba1a-8cfdfe2246dc_4950x2640.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ife-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7371b8-858e-4ccf-ba1a-8cfdfe2246dc_4950x2640.png 424w, https://substackcdn.com/image/fetch/$s_!ife-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7371b8-858e-4ccf-ba1a-8cfdfe2246dc_4950x2640.png 848w, https://substackcdn.com/image/fetch/$s_!ife-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7371b8-858e-4ccf-ba1a-8cfdfe2246dc_4950x2640.png 1272w, https://substackcdn.com/image/fetch/$s_!ife-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffe7371b8-858e-4ccf-ba1a-8cfdfe2246dc_4950x2640.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>The negotiation in the first five minutes</strong></p><p>Most candidates use the first five minutes to ask clarifying questions. How many users? What&#8217;s the read:write ratio? Does this need global availability?</p><p>These are fine questions. They&#8217;re also generic &#8212; they could be asked for any question. They don&#8217;t signal to the interviewer that you understand how to manage scope.</p><p>The candidates who score well on problem scoping don&#8217;t just ask questions. They propose scope.</p><p>&#8220;There are several interesting subsystems here: the timeline, search, notifications, the recommendation algorithm, and the ad serving layer. I&#8217;m going to focus on the timeline and the fan-out architecture. I&#8217;ll acknowledge the others exist and sketch where they&#8217;d connect, but I won&#8217;t design them in detail. Does that direction work for you?&#8221;</p><p>This is different from asking questions. You&#8217;re proposing what you&#8217;re going to design and explicitly not design, and you&#8217;re inviting the interviewer to redirect if they want something different.</p><p>Most interviewers will say yes. Some will redirect you: &#8220;Actually, I&#8217;m more interested in the fan-out problem for group chats specifically.&#8221; This is useful information you would not have gotten without proposing scope first.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe&quot;,&quot;text&quot;:&quot;Subscribe for WhatsApp Walkthrough&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://systemdr.systemdrd.com/subscribe"><span>Subscribe for WhatsApp Walkthrough</span></a></p><p><strong>Why the pressure to cover everything exists</strong></p><p>The instinct to design everything is understandable. The interview is evaluating your technical breadth, right? If you only design one component, won&#8217;t the interviewer think you don&#8217;t know the rest?</p><p>This misunderstands what the interview is evaluating.</p><p>Interviewers at L5+ levels are not checking whether you&#8217;ve memorized the architecture for every subsystem of Twitter. They know you&#8217;re familiar with notifications and search &#8212; you work as a software engineer. What they can&#8217;t infer from your resume is whether you can identify the hardest distributed systems problem in a question, scope down to it, and go deep enough to demonstrate real understanding.</p><p>Designing eight systems shallowly proves you&#8217;re familiar with eight systems. Designing one system deeply proves you can think through the hard parts of a complex problem. The second is what they&#8217;re scoring.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!SRqC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F984fa789-42fd-4484-a4da-f8cb0ff050a2_5060x2640.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!SRqC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F984fa789-42fd-4484-a4da-f8cb0ff050a2_5060x2640.png 424w, https://substackcdn.com/image/fetch/$s_!SRqC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F984fa789-42fd-4484-a4da-f8cb0ff050a2_5060x2640.png 848w, https://substackcdn.com/image/fetch/$s_!SRqC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F984fa789-42fd-4484-a4da-f8cb0ff050a2_5060x2640.png 1272w, https://substackcdn.com/image/fetch/$s_!SRqC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F984fa789-42fd-4484-a4da-f8cb0ff050a2_5060x2640.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!SRqC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F984fa789-42fd-4484-a4da-f8cb0ff050a2_5060x2640.png" width="1456" height="760" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/984fa789-42fd-4484-a4da-f8cb0ff050a2_5060x2640.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:760,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:836881,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.systemdrd.com/i/198936747?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F984fa789-42fd-4484-a4da-f8cb0ff050a2_5060x2640.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!SRqC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F984fa789-42fd-4484-a4da-f8cb0ff050a2_5060x2640.png 424w, https://substackcdn.com/image/fetch/$s_!SRqC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F984fa789-42fd-4484-a4da-f8cb0ff050a2_5060x2640.png 848w, https://substackcdn.com/image/fetch/$s_!SRqC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F984fa789-42fd-4484-a4da-f8cb0ff050a2_5060x2640.png 1272w, https://substackcdn.com/image/fetch/$s_!SRqC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F984fa789-42fd-4484-a4da-f8cb0ff050a2_5060x2640.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>How to choose what to scope in</strong></p><p>The right component to go deep on is the component with the most interesting distributed systems problem. Not the component you know best. Not the component that feels safest. The component where the answer is genuinely non-obvious.</p><p>For Twitter: the fan-out problem is more interesting than the user profile service. The timeline cache architecture is more interesting than the follow/unfollow API. Go where the hard problem lives.</p><p>A useful test: which component, if I described it at a surface level, would the interviewer immediately probe deeper on? That&#8217;s the component to start with.</p><p><strong>What to do with the components you&#8217;re not designing</strong></p><p>You don&#8217;t ignore them. You acknowledge them.</p><p>&#8220;Notifications would follow a standard fan-out-on-write pattern with push to APNs/FCM for mobile and WebSocket for web, similar to what we discussed for the timeline. I&#8217;m not going to design it in detail, but the interesting problem there is the delivery guarantee under failure &#8212; we&#8217;d need at-least-once delivery with client-side dedup.&#8221;</p><p>One sentence that shows you understand the problem, the standard solution, and the interesting edge case &#8212; without spending five minutes on a full design. This signals breadth without consuming depth time.</p><p><strong>The specific framing that works</strong></p><p>After the estimation section, before drawing anything, say this out loud:</p><p>&#8220;Before I draw the architecture, I want to lock scope. I&#8217;m going to go deep on [component X] because that&#8217;s where the interesting distributed systems problem is. I&#8217;ll acknowledge [components Y and Z] exist and show where they connect, but I won&#8217;t design them fully unless you&#8217;d like me to. Does that work?&#8221;</p><p>The explicit scope lock serves two purposes. It sets expectations so the interviewer isn&#8217;t waiting for you to cover components you&#8217;ve already decided to skip. And it gives the interviewer one last opportunity to redirect before you&#8217;ve committed 30 minutes to the wrong area.</p><p>After this moment, the scope is locked. Don&#8217;t drift. If you finish the deep dive early, go deeper on the component you chose &#8212; don&#8217;t add new components to fill time.</p><p><strong>The uncomfortable truth about breadth</strong></p><p>Demonstrating breadth is valuable. Demonstrating it through shallow coverage of many components is not the right way.</p><p>The right way: show breadth through the quality of your acknowledgments. When you mention a component you&#8217;re not designing and you correctly name the problem it has and the standard approach for solving it, you&#8217;ve shown breadth in one sentence. Compare that to spending five minutes on a shallow design of the same component &#8212; same signal, five minutes cheaper.</p><p>Scope discipline isn&#8217;t about knowing less. It&#8217;s about deploying what you know efficiently enough to demonstrate depth where it matters.</p><div><hr></div><p><strong>CTA:</strong> Tuesday&#8217;s paid post is the full WhatsApp walkthrough &#8212; including how to scope it correctly when the question says &#8220;design a messaging system&#8221; and you have 50 minutes. </p><h2><strong>Subscription link</strong></h2><p><a href="https://systemdr.systemdrd.com/subscribe">https://systemdr.systemdrd.com/subscribe</a></p><p>&#8212;Sumedh</p><div class="callout-block" data-callout="true"><p>The Question Vault has all 52 walkthroughs organized by archetype &#8212; so you can see the pattern across questions, not just the surface answer.</p><p><strong>Access all 52 Quesstions <a href="https://systemdrd.com/ebooks/52-faang-questions-drillcards-cheatsheets/">here</a></strong></p></div><p><strong>Curious how this works in real systems?</strong> </p><p>The paid lessons cover scalability, optimization, and real-world engineering patterns.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">System Design Interview Roadmap is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Log Aggregation at Scale: ELK vs. Splunk vs. Loki Architectures]]></title><description><![CDATA[Sponsored]]></description><link>https://systemdr.systemdrd.com/p/log-aggregation-at-scale-elk-vs-splunk</link><guid isPermaLink="false">https://systemdr.systemdrd.com/p/log-aggregation-at-scale-elk-vs-splunk</guid><dc:creator><![CDATA[System Design Roadmap]]></dc:creator><pubDate>Fri, 19 Jun 2026 08:15:36 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!hvEx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f483a82-9a04-4842-bca9-7e77e2530be3_4500x3100.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="callout-block" data-callout="true"><p style="text-align: center;"><strong><span data-color="#1155cc" style="color: rgb(17, 85, 204);">Sponsored </span></strong></p><p>Build Distritubed Systems using System Design concepts with hands-on coding lessons every day - <a href="https://sdcourse.substack.com/">System Design Course</a></p><p><strong>Preparing for a distributed systems interview?</strong></p><p><a href="https://systemdrd.com/courses/system-design-dsa/">&#8594; Get the Complete System Design &amp; DSA Framework</a></p><p><a href="https://systemdrd.com/courses/troubleshooting-distributed-java-systems/">&#8594; Deep-Dive: Troubleshooting Distributed Java Systems</a></p></div><h2>Introduction</h2><blockquote><p>Your production system just went dark at 2:47 AM. Services are returning 503s, customers are screaming, and your on-call engineer is frantically searching through logs scattered across 200 containers on 40 nodes. Without a centralized log aggregation system, every second spent grepping individual machines is a second your system stays broken. Log aggregation isn&#8217;t just a nice-to-have &#8212; it&#8217;s the difference between a 4-minute MTTR and a 4-hour incident.</p></blockquote><div><hr></div><h2>Core Concept: What Log Aggregation Actually Does</h2><p>At its core, log aggregation solves a distributed systems problem: your logs are generated everywhere, but your engineers need to query them from one place. Every log aggregation system shares the same pipeline, regardless of branding: <strong>collect &#8594; ship &#8594; parse &#8594; index &#8594; query</strong>.</p><p>The architectural divergence happens at indexing and query layers, and those differences have enormous operational and cost consequences at scale.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">System Design Interview Roadmap is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p><strong>The Collection Layer</strong> is where agents like Filebeat, Promtail, or Splunk Universal Forwarder tail log files or consume stdout/stderr from containers. These agents buffer locally (critical for handling backpressure), add metadata (hostname, container ID, Kubernetes labels), and ship upstream. The key failure mode here is the &#8220;silent drop&#8221; &#8212; when the downstream ingestion endpoint is overwhelmed, poorly configured agents discard logs rather than applying backpressure. You lose exactly the logs you need most: the ones generated during an incident when traffic spikes.</p><p><strong>The Ingestion Layer</strong> (Logstash, Fluentd, or Splunk Indexers) performs parsing, enrichment, and routing. This is where unstructured log lines become structured JSON documents. At scale, this layer becomes a bottleneck. A single Logstash pipeline on modest hardware handles roughly 10,000-50,000 events/second. Facebook&#8217;s internal systems process petabytes of logs daily &#8212; they&#8217;ve replaced traditional parsing pipelines with stream processors that apply schema-on-read rather than schema-on-write, deferring expensive parsing until query time.</p><p><strong>The Storage and Index Layer</strong> is where the three major architectures diverge fundamentally.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!hvEx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f483a82-9a04-4842-bca9-7e77e2530be3_4500x3100.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!hvEx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f483a82-9a04-4842-bca9-7e77e2530be3_4500x3100.png 424w, https://substackcdn.com/image/fetch/$s_!hvEx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f483a82-9a04-4842-bca9-7e77e2530be3_4500x3100.png 848w, https://substackcdn.com/image/fetch/$s_!hvEx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f483a82-9a04-4842-bca9-7e77e2530be3_4500x3100.png 1272w, https://substackcdn.com/image/fetch/$s_!hvEx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f483a82-9a04-4842-bca9-7e77e2530be3_4500x3100.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!hvEx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f483a82-9a04-4842-bca9-7e77e2530be3_4500x3100.png" width="1456" height="1003" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5f483a82-9a04-4842-bca9-7e77e2530be3_4500x3100.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1003,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2717603,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.substack.com/i/190587959?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f483a82-9a04-4842-bca9-7e77e2530be3_4500x3100.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!hvEx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f483a82-9a04-4842-bca9-7e77e2530be3_4500x3100.png 424w, https://substackcdn.com/image/fetch/$s_!hvEx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f483a82-9a04-4842-bca9-7e77e2530be3_4500x3100.png 848w, https://substackcdn.com/image/fetch/$s_!hvEx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f483a82-9a04-4842-bca9-7e77e2530be3_4500x3100.png 1272w, https://substackcdn.com/image/fetch/$s_!hvEx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f483a82-9a04-4842-bca9-7e77e2530be3_4500x3100.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>ELK Stack (Elasticsearch, Logstash, Kibana)</h3><blockquote><p>Elasticsearch uses an inverted index on every field by default. When you ingest a log line, Elasticsearch tokenizes every string value and creates a lookup from token &#8594; document IDs. This makes full-text search blazing fast &#8212; querying &#8220;ERROR database connection&#8221; across 100GB of logs takes milliseconds. The cost: indexing overhead is enormous. Elasticsearch uses approximately <strong>3-10x the raw log size</strong> in index storage. A 1TB/day log pipeline requires 3-10TB of SSD storage &#8212; and Elasticsearch performs poorly on spinning disks.</p></blockquote><p>The shard architecture adds operational complexity. An index is split into shards, and each shard is a self-contained Lucene index. Too few shards and you bottleneck on single-node write throughput. Too many shards (over-sharding) causes cluster state overhead that degrades all operations. The golden ratio that works in most production clusters: <strong>shard size between 10-50GB, with 1-2 primary shards per node&#8217;s CPU core count</strong>.</p><h3>Splunk</h3><blockquote><p>Splunk is architecturally similar to ELK but adds a proprietary compressed index format and a more powerful query language (SPL). Its key differentiator is schema-on-read: Splunk extracts fields at search time rather than index time. This makes ingestion faster but search slower for first-time queries. Splunk&#8217;s SmartStore tiering (hot/warm/cold to S3) is genuinely excellent for cost management &#8212; organizations commonly achieve 70-80% storage cost reduction by moving 90-day+ data to object storage.</p></blockquote><p>The hidden cost is licensing. Splunk&#8217;s volume-based pricing ($50-150/GB/day for enterprise licenses) makes it the most expensive option at scale. At 500GB/day ingestion, annual costs can exceed $10M. This is why large organizations often run Splunk for security/compliance workloads (where its SIEM capabilities justify cost) and migrate general application logs to ELK or Loki.</p><h3>Grafana Loki</h3><blockquote><p>Loki takes a fundamentally different approach: <strong>it only indexes labels, not log content</strong>. A Loki stream is identified by a set of key-value labels (<code>{app="payments", env="prod"}</code>). The log lines themselves are stored compressed in chunks in object storage (S3, GCS) without content indexing.</p></blockquote><p>This makes Loki dramatically cheaper &#8212; storage costs are close to raw log size, often <strong>10-20x cheaper than Elasticsearch</strong> at equivalent volume. The trade-off is query performance. To search log content, Loki must decompress and scan chunks sequentially. A grep-style query across 24 hours of logs on a single service is fast (it finds the right chunks via label index). A query across all services for a specific string pattern requires scanning everything &#8212; and is orders of magnitude slower than Elasticsearch for that access pattern.</p><p>Loki&#8217;s architecture is intentionally Kubernetes-native. Its label model mirrors Prometheus labels, making it trivially easy to correlate metrics and logs on the same infrastructure. The <code>logcli</code> tool and LogQL query language will feel immediately familiar to anyone using PromQL.</p><div><hr></div><div class="callout-block" data-callout="true"><p style="text-align: center;"><strong><span data-color="rgb(156, 163, 175)" style="color: rgb(156, 163, 175);">A message from our partner</span></strong></p><h3 style="text-align: center;"><strong>Struggling to Learn distributed Systems with Go?</strong></h3><p>Building advanced applications is incredible, but keeping them scaling smoothly under real load is where engineering mastery lives. Learn how to construct high-performance infrastructures using Google&#8217;s <strong>Go language</strong>, or master deep diagnostic tactics for tracking down complex runtime failures in live, <strong>distributed Java environments</strong>.</p><p>Stop guessing when exceptions hit production. Level up your skill set from standard script execution to architecture-level systems engineering.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://systemdrd.com/courses/system-enginnering-go/&quot;,&quot;text&quot;:&quot;Learn Distributed Systems with GO&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://systemdrd.com/courses/system-enginnering-go/"><span>Learn Distributed Systems with GO</span></a></p></div><div><hr></div><h2>Critical Insights</h2><p><strong>1. Cardinality Is the Killer (Loki):</strong> Loki&#8217;s index contains all unique label combinations. If you add <code>user_id</code> or <code>request_id</code> as a label, you explode cardinality &#8212; potentially millions of unique streams. This causes memory exhaustion in the ingester and dramatically degrades query performance. Keep label cardinality under 10,000 unique values per label dimension. User IDs belong in log content, not labels.</p><p><strong>2. Elasticsearch Split-Brain Is Underestimated:</strong> When the cluster loses quorum (network partition, node failure during rolling restart), Elasticsearch can enter split-brain: two cluster halves both believe they are primary. Both accept writes. When the partition heals, one side&#8217;s data is lost. The mitigation is setting <code>minimum_master_nodes = (N/2)+1</code> &#8212; but many teams run with defaults and discover this during their worst incident.</p><p><strong>3. Logstash Memory Leaks in Pipeline Restarts:</strong> Logstash uses the JVM with a persistent queue on disk. During unclean restarts (OOM kill, SIGKILL), the queue can become corrupted. Events between the last checkpoint and the crash are reprocessed (duplicates) or lost (if queue corruption is severe). Switching to Filebeat + direct Elasticsearch ingest pipelines eliminates Logstash as a single point of failure &#8212; and reduces the pipeline&#8217;s memory footprint by 60-80%.</p><p><strong>4. The Hot Shard Problem (Elasticsearch):</strong> If all your services use time-based index names (<code>logs-2025.01.15</code>), all write traffic hits today&#8217;s index. The shards for today&#8217;s index receive 100% of writes while yesterday&#8217;s shards sit idle. Index lifecycle management (ILM) with rollover policies (roll when shard hits 30GB or 24h) distributes writes more evenly and prevents the &#8220;hot shard&#8221; bottleneck.</p><p><strong>5. Retention Policy Mismatch:</strong> Most teams set a single retention policy. Production reality: security logs need 1-year retention (compliance), application debug logs need 7 days (cost), and business metrics need 90 days (analytics). ELK&#8217;s index-per-service-per-retention-tier architecture and Loki&#8217;s label-based bucket policies both support this &#8212; but require explicit configuration. Defaulting to uniform retention is a significant hidden cost.</p><p><strong>6. Structured Logging Multiplier Effect:</strong> Teams that enforce structured JSON logging (every log line is valid JSON with consistent field names) get dramatically better results from any aggregation system. Field extraction at parse time is zero-cost. Ad-hoc grok pattern matching on unstructured text adds 30-50% CPU overhead to Logstash/Fluentd pipelines and produces inconsistent results when log formats change.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!amAh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5d6c3c8-a145-4612-8d6d-f7d475897a7d_4500x3200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!amAh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5d6c3c8-a145-4612-8d6d-f7d475897a7d_4500x3200.png 424w, https://substackcdn.com/image/fetch/$s_!amAh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5d6c3c8-a145-4612-8d6d-f7d475897a7d_4500x3200.png 848w, https://substackcdn.com/image/fetch/$s_!amAh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5d6c3c8-a145-4612-8d6d-f7d475897a7d_4500x3200.png 1272w, https://substackcdn.com/image/fetch/$s_!amAh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5d6c3c8-a145-4612-8d6d-f7d475897a7d_4500x3200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!amAh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5d6c3c8-a145-4612-8d6d-f7d475897a7d_4500x3200.png" width="1456" height="1035" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b5d6c3c8-a145-4612-8d6d-f7d475897a7d_4500x3200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1035,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2351140,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.substack.com/i/190587959?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5d6c3c8-a145-4612-8d6d-f7d475897a7d_4500x3200.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!amAh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5d6c3c8-a145-4612-8d6d-f7d475897a7d_4500x3200.png 424w, https://substackcdn.com/image/fetch/$s_!amAh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5d6c3c8-a145-4612-8d6d-f7d475897a7d_4500x3200.png 848w, https://substackcdn.com/image/fetch/$s_!amAh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5d6c3c8-a145-4612-8d6d-f7d475897a7d_4500x3200.png 1272w, https://substackcdn.com/image/fetch/$s_!amAh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5d6c3c8-a145-4612-8d6d-f7d475897a7d_4500x3200.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><h2>Real-World Examples</h2><p><strong>Uber&#8217;s Migration Away from Elasticsearch:</strong> Uber ran one of the largest ELK deployments in the industry &#8212; 600TB+ of log data. They hit fundamental limits on reindexing speed during schema migrations and cluster-wide query performance degradation during peak traffic. Their solution was a hybrid: ELK for recent 7-day hot data (fast search), Apache Hive on HDFS for cold storage (cheap retention). This pattern &#8212; tiered storage with different query semantics per tier &#8212; is now standard at hyperscale.</p><p><strong>Cloudflare&#8217;s Loki Adoption:</strong> Cloudflare handles ~50 million HTTP requests/second across their edge. Their logging pipeline using Loki with label-based routing reduced storage costs by 85% compared to their previous Elasticsearch deployment, at the cost of accepting slower ad-hoc content searches. For their use case (known-structure queries, metric correlation, alerting), this trade-off was acceptable.</p><p><strong>Splunk for Security, Not Application Logs:</strong> JPMorgan Chase and similar financial institutions maintain Splunk exclusively for SIEM workloads &#8212; security event correlation, compliance reporting, and anomaly detection where SPL&#8217;s power and Splunk&#8217;s security content library justify the cost. Application performance logs run on ELK with cold-tier archival to S3 via Searchable Snapshots.</p><div><hr></div><h2>Architectural Considerations</h2><p>Log aggregation integrates directly with your alerting layer &#8212; Kibana/Grafana can trigger PagerDuty alerts on log patterns, but this creates a hidden coupling between storage availability and incident response. If your log cluster is unhealthy during an incident, you lose both visibility and alerting simultaneously. The mitigation: route critical structured events (errors, exceptions) to a separate, lightweight stream (Kafka + minimal consumer) that feeds alerting independently of the full log pipeline.</p><blockquote><p>Cost modeling matters here. Elasticsearch at 100GB/day ingestion runs approximately $15,000-25,000/month on cloud infrastructure when accounting for multi-replica storage, hot node compute, and snapshot costs. Loki on the same workload runs $2,000-5,000/month. The break-even analysis depends entirely on your query access patterns &#8212; if your team runs full-text searches across all services constantly, Elasticsearch&#8217;s performance advantage may justify the cost.</p></blockquote><div><hr></div><h2>Practical Takeaway</h2><h2><strong>GitHub Link</strong></h2><p><strong><a href="https://github.com/sysdr/sdir/tree/main/Log_Aggregation_at_scale/log-aggregation-demo">https://github.com/sysdr/sdir/tree/main/Log_Aggregation_at_scale/log-aggregation-demo</a></strong></p><p>The right log aggregation architecture depends on your query patterns, not your log volume. Full-text search across diverse log formats &#8594; Elasticsearch. Metric-correlated log tailing on Kubernetes &#8594; Loki. Compliance and security analytics with budget &#8594; Splunk.</p><p><strong>Run the demo:</strong></p><p>bash</p><pre><code><code>bash setup.sh</code></code></pre><p>The demo spins up a local Loki + Grafana stack alongside a simulated Elasticsearch cluster, with a synthetic load generator producing structured log streams. You&#8217;ll see:</p><ul><li><p>Label cardinality impact on Loki query performance in real time</p></li><li><p>Elasticsearch index hot-shard behavior under write load</p></li><li><p>Side-by-side query latency comparison for identical workloads</p></li></ul><p>Extend the demo by modifying <code>load-generator/config.json</code> to increase cardinality (add <code>user_id</code> as a Loki label) and watch query performance degrade. This is the single most important failure pattern to understand before deploying Loki in production.</p><div class="callout-block" data-callout="true"><p><strong><span data-color="#1155cc" style="color: rgb(17, 85, 204);">Sponsored </span>Systemdr Distributed Architecture:</strong><span data-color="rgb(31, 41, 55)" style="color: rgb(31, 41, 55);"> Preparing for heavy-scale backend interviews or architecting massive infrastructure? Master production-grade concepts with hands-on labs covering high-scale distributed engineering, system design, and algorithmic strategies. </span><strong><a href="https://systemdrd.com/courses/system-design-dsa/">Learn more here &#8594;</a></strong></p></div><div><hr></div><h3>Youtube Demo Link:</h3><div id="youtube2-jiPIquaSH88" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;jiPIquaSH88&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/jiPIquaSH88?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">System Design Interview Roadmap is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Design Uber Dispatch — The Senior+ Walkthrough]]></title><description><![CDATA[This is the question that defines the marketplace and matching archetype.]]></description><link>https://systemdr.systemdrd.com/p/design-uber-dispatch-the-senior-walkthrough</link><guid isPermaLink="false">https://systemdr.systemdrd.com/p/design-uber-dispatch-the-senior-walkthrough</guid><dc:creator><![CDATA[System Design Roadmap]]></dc:creator><pubDate>Tue, 16 Jun 2026 03:30:36 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!X5Su!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff94c092b-6e6d-42a4-906c-81bdd893ef09_2048x1341.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote><p>This is the question that defines the marketplace and matching archetype. Ten questions in the question bank are variants of it &#8212; DoorDash delivery, Airbnb booking, Tinder matching, parking reservation, surge pricing, ride-share fraud. They share a spine: a supply side, a demand side, a location component, and a real-time matching requirement. The architecture that works for Uber dispatch, with minimal modification, works for all ten.</p></blockquote><blockquote><p>The surface question &#8212; &#8220;design Uber&#8221; &#8212; is a 4-hour answer. Interviewers narrow it deliberately: &#8220;design the dispatch system,&#8221; &#8220;design how a driver gets matched to a rider,&#8221; &#8220;walk me through what happens between the rider hitting &#8216;Request&#8217; and the driver getting a notification.&#8221; All three collapse to the same probe: <strong>how do you find the nearest available supply in real time, at scale, without burning down your database on every request?</strong></p></blockquote><p>The answer involves a data structure most candidates haven&#8217;t touched since their algorithms course: geospatial indexing. Specifically, quadtrees or geohashing &#8212; and knowing <em>which one</em> and <em>why</em> is the senior signal.</p><p>For L4 / mid-level: describe the matching flow and a naive approach. For L5 / senior: articulate the geospatial indexing choice with its trade-offs. For L6 / staff: the consistency model across supply/demand state, the surge pricing data flow, multi-city scaling, and what happens when a driver&#8217;s GPS signal drops.</p><div><hr></div><h2>The Question</h2><blockquote><p>&#8220;Design the Uber dispatch system. A rider requests a ride. The system finds nearby available drivers and assigns one to the rider.&#8221;</p></blockquote><p>Common variants:</p><ul><li><p>&#8220;Design DoorDash / UberEats food delivery dispatch.&#8221;</p></li><li><p>&#8220;Design Lyft&#8217;s matching system.&#8221;</p></li><li><p>&#8220;Design a system to match drivers to delivery orders in real time.&#8221;</p></li><li><p>&#8220;Design the driver-to-rider matching at Uber.&#8221;</p></li></ul><p>All four are the same architecture. DoorDash has one additional dimension &#8212; the restaurant (a fixed supply point instead of a moving one) &#8212; but the matching logic is identical.</p><div><hr></div><h2>Step 1 &#8212; Clarify Before You Draw</h2><p>Six questions. Two of them are load-bearing for the whole design.</p><p><strong>1. What does &#8220;dispatch&#8221; include &#8212; match only, or also route and surge?</strong> Dispatch in the narrow sense is &#8220;find a driver and assign them to a rider.&#8221; Routing (which road to take) is a separate system (Google Maps API or in-house). Surge pricing (dynamic fare) is another separate system. Clarify scope explicitly. Design the matching layer; acknowledge the others exist.</p><p><strong>2. How many active drivers? What&#8217;s the geography &#8212; one city or global?</strong> Active drivers in a single city: tens of thousands. Globally: millions. This shapes whether your geo-index fits in memory on one machine or needs distribution. For a US metro at peak, 10,000&#8211;50,000 active drivers is a reasonable working number. Global scale: 5&#8211;10M.</p><p><strong>3. How frequently do drivers update their location?</strong> Every 4&#8211;5 seconds is typical. This is a high-frequency write stream &#8212; 50,000 drivers &#215; 1 write/4s = ~12,500 writes/sec in one busy metro. Globally: millions of writes/sec. State this number; it drives the design of the location ingestion layer.</p><p><strong>4. What&#8217;s the matching latency SLO?</strong> A rider hits &#8220;request&#8221; and expects a driver to accept within 30&#8211;60 seconds. The matching decision itself should happen in milliseconds &#8212; sub-100ms for the initial candidate selection. If it takes 5 seconds to find a candidate, the experience breaks.</p><p><strong>5. Can a driver be matched to multiple requests simultaneously?</strong> No &#8212; a driver has one state: available or not. This is the consistency problem at the heart of the question. Two riders cannot be dispatched to the same driver. The system that manages this state is load-bearing.</p><p><strong>6. What failure modes matter most?</strong> Driver goes offline mid-trip. GPS signal drops. Driver declines the match. Rider cancels after match. Each one requires a state machine transition. State the three most important ones out loud.</p><div><hr></div><h2>Step 2 &#8212; Estimate</h2><p>Working assumptions for a single large metro deployment:</p><ul><li><p>50,000 active drivers at peak</p></li><li><p>200,000 ride requests per hour at peak = ~55 ride requests/sec</p></li><li><p>Driver location update: every 4 seconds, so 50,000 / 4 = 12,500 location writes/sec</p></li><li><p>Matching query: for every ride request, find all drivers within ~2 km radius</p></li><li><p>Average matching candidate set: 20&#8211;50 drivers</p></li><li><p>End-to-end dispatch latency target: &lt; 100ms for candidate selection, &lt; 30s for driver acceptance</p></li></ul><p>Location data per driver per update: ~100 bytes (driver_id, lat/lng, timestamp, status).</p><p>Writes: 12,500/s &#215; 100 bytes &#8776; 1.25 MB/s. Trivial for a single machine.</p><p>If global (5M drivers): 5M / 4 = 1.25M writes/sec. Serious &#8212; needs distributed location ingestion. But for this walkthrough, start with the single-metro case and note the global extension.</p><p>The geo-index in memory for 50,000 drivers: 50,000 &#215; 100 bytes = 5 MB. <em>Fits entirely in memory on a single machine.</em> This insight &#8212; that the active driver set for one city is tiny &#8212; is what enables the in-memory geo-index approach.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://systemdr.systemdrd.com/subscribe&quot;,&quot;text&quot;:&quot;Get Access to GitHub Repo&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://systemdr.systemdrd.com/subscribe"><span>Get Access to GitHub Repo</span></a></p><div><hr></div><h2>Step 3 &#8212; API Design</h2><p>Three endpoints. The first is rider-facing, the second is driver-facing, the third is the internal matching call.</p><div class="callout-block" data-callout="true"><p>POST /v1/rides/request</p><p>Headers:</p><p>  Authorization: Bearer {rider_token}</p><p>Body:</p><p>  pickup_lat: float</p><p>  pickup_lng: float</p><p>  destination_lat: float</p><p>  destination_lng: float</p><p>  ride_type: &#8220;uberx&#8221; | &#8220;pool&#8221; | &#8220;xl&#8221; | &#8220;black&#8221;</p><p>Response:</p><p>  ride_id: &#8220;r_xxx&#8221;</p><p>  status: &#8220;searching&#8221;</p><p>  eta_to_pickup_seconds: integer (estimate, not a promise)</p><p>  price_estimate: { low_cents, high_cents, surge_multiplier }</p><p>PUT /v1/drivers/location</p><p>Headers:</p><p>  Authorization: Bearer {driver_token}</p><p>Body:</p><p>  lat: float</p><p>  lng: float</p><p>  heading: float (degrees)</p><p>  speed_mps: float (meters/sec)</p><p>  status: &#8220;available&#8221; | &#8220;on_trip&#8221; | &#8220;offline&#8221;</p><p>Response: 200 (ack)</p><p>POST /v1/dispatch/match   (internal, not public-facing)</p><p>Body:</p><p>  ride_id: &#8220;r_xxx&#8221;</p><p>  pickup_lat, pickup_lng</p><p>  ride_type</p><p>Response:</p><p>  candidate_drivers: [{ driver_id, distance_meters, eta_seconds, rating }]</p></div><p><strong>The senior move on location updates:</strong> note that the driver app batches and sends at 4-second intervals, not on every GPS tick (which might be 1-second intervals). Batching reduces write load by 4x and extends driver battery life. Saying this out loud &#8212; that the <em>client</em> has a role in write amplification &#8212; is an insight most candidates miss.</p><p><strong>heading and speed_mps</strong> in the location update. Junior candidates send only lat/lng. Senior candidates send velocity vector too. Why: ETA estimation to a pickup point requires knowing not just where the driver is but which way they&#8217;re going and how fast. A driver 500m away facing the wrong direction on a one-way street is further than a driver 700m away pointed at you. The heading/speed fields feed the ETA model.</p><div><hr></div><h2>Step 4 &#8212; Data Model</h2><p>Four stores. The geo-index is the unusual one.</p><h3>drivers table &#8212; source of truth for driver state</h3><p>driver_id, name, vehicle_type, license_plate, rating_avg, total_trips,</p><p>current_status (ENUM: available/on_trip/offline/suspended),</p><p>current_lat, current_lng, last_location_update, created_at</p><p>Sharded by driver_id. The current_status and current_lat/lng columns are updated frequently &#8212; this is the consistency-critical state. More on that in Step 6.</p><h3>rides table &#8212; the ride state machine</h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!KsEo!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0696dbad-e66d-47bd-ad8e-b5ed032c76da_1157x457.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!KsEo!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0696dbad-e66d-47bd-ad8e-b5ed032c76da_1157x457.png 424w, https://substackcdn.com/image/fetch/$s_!KsEo!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0696dbad-e66d-47bd-ad8e-b5ed032c76da_1157x457.png 848w, https://substackcdn.com/image/fetch/$s_!KsEo!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0696dbad-e66d-47bd-ad8e-b5ed032c76da_1157x457.png 1272w, https://substackcdn.com/image/fetch/$s_!KsEo!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0696dbad-e66d-47bd-ad8e-b5ed032c76da_1157x457.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!KsEo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0696dbad-e66d-47bd-ad8e-b5ed032c76da_1157x457.png" width="1157" height="457" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0696dbad-e66d-47bd-ad8e-b5ed032c76da_1157x457.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:457,&quot;width&quot;:1157,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:84112,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.systemdrd.com/i/201697493?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0696dbad-e66d-47bd-ad8e-b5ed032c76da_1157x457.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!KsEo!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0696dbad-e66d-47bd-ad8e-b5ed032c76da_1157x457.png 424w, https://substackcdn.com/image/fetch/$s_!KsEo!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0696dbad-e66d-47bd-ad8e-b5ed032c76da_1157x457.png 848w, https://substackcdn.com/image/fetch/$s_!KsEo!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0696dbad-e66d-47bd-ad8e-b5ed032c76da_1157x457.png 1272w, https://substackcdn.com/image/fetch/$s_!KsEo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0696dbad-e66d-47bd-ad8e-b5ed032c76da_1157x457.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!UHAO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F493fdbf1-f3d3-4f15-b030-a33635aad5a0_862x345.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UHAO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F493fdbf1-f3d3-4f15-b030-a33635aad5a0_862x345.png 424w, https://substackcdn.com/image/fetch/$s_!UHAO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F493fdbf1-f3d3-4f15-b030-a33635aad5a0_862x345.png 848w, https://substackcdn.com/image/fetch/$s_!UHAO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F493fdbf1-f3d3-4f15-b030-a33635aad5a0_862x345.png 1272w, https://substackcdn.com/image/fetch/$s_!UHAO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F493fdbf1-f3d3-4f15-b030-a33635aad5a0_862x345.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!UHAO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F493fdbf1-f3d3-4f15-b030-a33635aad5a0_862x345.png" width="862" height="345" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/493fdbf1-f3d3-4f15-b030-a33635aad5a0_862x345.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:345,&quot;width&quot;:862,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:41337,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://systemdr.systemdrd.com/i/201697493?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F493fdbf1-f3d3-4f15-b030-a33635aad5a0_862x345.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!UHAO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F493fdbf1-f3d3-4f15-b030-a33635aad5a0_862x345.png 424w, https://substackcdn.com/image/fetch/$s_!UHAO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F493fdbf1-f3d3-4f15-b030-a33635aad5a0_862x345.png 848w, https://substackcdn.com/image/fetch/$s_!UHAO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F493fdbf1-f3d3-4f15-b030-a33635aad5a0_862x345.png 1272w, https://substackcdn.com/image/fetch/$s_!UHAO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F493fdbf1-f3d3-4f15-b030-a33635aad5a0_862x345.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Ride state machine:</strong> searching &#8594; matched (driver found) &#8594; accepted (driver acknowledged) &#8594; driver_en_route &#8594; arrived &#8594; in_progress &#8594; completed | cancelled</p><p>Any state can transition to cancelled. The driver_id is only set at the matched transition. If a driver declines, status reverts to searching and the matching process re-runs.</p><h3>location_history &#8212; time series store</h3><p>Not your OLTP database. Location events are time-series data: (driver_id, lat, lng, timestamp, heading, speed). At 12,500 events/sec, that&#8217;s 1 billion events/day in one metro. You don&#8217;t store this in Postgres. You use a time-series database (InfluxDB, TimescaleDB, Cassandra with a time-ordered key) or push to a data lake for analytics.</p><p>The hot query (&#8221;where is this driver right now?&#8221;) hits the geo-index, not this table. This table is for analytics, replay, and dispute resolution (&#8221;I was at X at time T &#8212; prove it&#8221;).</p><h3>driver_geo_index &#8212; the in-memory geo-index</h3><p>This is the heart of the system. Not a SQL table. An in-memory spatial index that answers &#8220;which drivers are within radius R of point (lat, lng) in sub-millisecond time.&#8221;</p><p>Two real options: <strong>quadtrees</strong> or <strong>geohashing</strong>. This is Step 6&#8217;s deep dive.</p><div class="callout-block" data-callout="true"><p>Preparing for a distributed systems interview?<br>&#8594;<a href="https://systemdrd.com/ebooks/sdcourse-distributed-systems-interview">Download the free Interview Pack</a><br>&#8594; <a href="https://systemdr.systemdrd.com/subscribe">Subscribe</a> now to access source code repository - 200 + coding lessons</p></div>
      <p>
          <a href="https://systemdr.systemdrd.com/p/design-uber-dispatch-the-senior-walkthrough">
              Read more
          </a>
      </p>
   ]]></content:encoded></item></channel></rss>