<?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[SystemDesignLaws]]></title><description><![CDATA[This newsletter is easy to follow and covers core components of system design and how start-ups and big companies do it. Upgrade your career.]]></description><link>https://newsletter.systemdesignlaws.xyz</link><image><url>https://substackcdn.com/image/fetch/$s_!1UhY!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe079dd84-d487-4144-b771-e921eea5c7bf_224x224.png</url><title>SystemDesignLaws</title><link>https://newsletter.systemdesignlaws.xyz</link></image><generator>Substack</generator><lastBuildDate>Tue, 03 Nov 2026 18:56:06 GMT</lastBuildDate><atom:link href="https://newsletter.systemdesignlaws.xyz/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Jimmy Malhan]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[jimmymalhan@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[jimmymalhan@substack.com]]></itunes:email><itunes:name><![CDATA[Jimmy Malhan]]></itunes:name></itunes:owner><itunes:author><![CDATA[Jimmy Malhan]]></itunes:author><googleplay:owner><![CDATA[jimmymalhan@substack.com]]></googleplay:owner><googleplay:email><![CDATA[jimmymalhan@substack.com]]></googleplay:email><googleplay:author><![CDATA[Jimmy Malhan]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Consistent Hashing]]></title><description><![CDATA[Add one server and move about 20% of keys: the ring, virtual nodes and replicas, ready for interviews]]></description><link>https://newsletter.systemdesignlaws.xyz/p/consistent-hashing</link><guid isPermaLink="false">https://newsletter.systemdesignlaws.xyz/p/consistent-hashing</guid><dc:creator><![CDATA[Jimmy Malhan]]></dc:creator><pubDate>Tue, 03 Nov 2026 17:02:02 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!CGu8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6dab3f4d-4faa-4dc7-b9f9-d513c9bda4b7_1092x1092.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CGu8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6dab3f4d-4faa-4dc7-b9f9-d513c9bda4b7_1092x1092.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CGu8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6dab3f4d-4faa-4dc7-b9f9-d513c9bda4b7_1092x1092.png 424w, https://substackcdn.com/image/fetch/$s_!CGu8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6dab3f4d-4faa-4dc7-b9f9-d513c9bda4b7_1092x1092.png 848w, https://substackcdn.com/image/fetch/$s_!CGu8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6dab3f4d-4faa-4dc7-b9f9-d513c9bda4b7_1092x1092.png 1272w, https://substackcdn.com/image/fetch/$s_!CGu8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6dab3f4d-4faa-4dc7-b9f9-d513c9bda4b7_1092x1092.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CGu8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6dab3f4d-4faa-4dc7-b9f9-d513c9bda4b7_1092x1092.png" width="1092" height="1092" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6dab3f4d-4faa-4dc7-b9f9-d513c9bda4b7_1092x1092.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1092,&quot;width&quot;:1092,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1775298,&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://newsletter.systemdesignlaws.xyz/i/222168462?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6dab3f4d-4faa-4dc7-b9f9-d513c9bda4b7_1092x1092.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_!CGu8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6dab3f4d-4faa-4dc7-b9f9-d513c9bda4b7_1092x1092.png 424w, https://substackcdn.com/image/fetch/$s_!CGu8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6dab3f4d-4faa-4dc7-b9f9-d513c9bda4b7_1092x1092.png 848w, https://substackcdn.com/image/fetch/$s_!CGu8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6dab3f4d-4faa-4dc7-b9f9-d513c9bda4b7_1092x1092.png 1272w, https://substackcdn.com/image/fetch/$s_!CGu8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6dab3f4d-4faa-4dc7-b9f9-d513c9bda4b7_1092x1092.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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>TL;DR</strong> - Modulo hashing reshuffles almost every key when the cluster size changes. Consistent hashing puts nodes and keys on a ring so a membership change moves about 1/N of the keys. Add virtual nodes for even load, walk the ring for replicas, and remember it balances keys; traffic needs its own fix.</p><blockquote><p>30-second elevator pitch: &#8220;I map keys and servers onto the same hash ring. A key belongs to the first server clockwise from it. When a server joins or dies, one slice of the ring changes owner. Each server gets many virtual positions, so load stays even and a failure spreads evenly across all survivors.&#8221;</p></blockquote><div><hr></div><h2>Why Modulo Hashing Reshuffles on Resize</h2><p>You run a cache tier with 4 servers and route with server = hash(key) mod 4. It is fast, stateless, and even. Then you add a fifth server.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://newsletter.systemdesignlaws.xyz/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">SystemDesignLaws 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>Under hash(key) mod 5, a key stays put exactly when its hash leaves the same remainder under both divisors. For uniform hashes that happens with probability 1/(N+1), so going from 4 to 5 servers keeps 20 percent of keys and moves 80 percent. In general, adding one node to N moves N/(N+1) of all keys.</p><p>For a cache, that is a miss storm that dumps reads onto the database. For a sharded database, it means copying most of the dataset to add capacity.</p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9UfK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F210afab3-f500-4b13-81da-7afaf89d9568_980x1216.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9UfK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F210afab3-f500-4b13-81da-7afaf89d9568_980x1216.png 424w, https://substackcdn.com/image/fetch/$s_!9UfK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F210afab3-f500-4b13-81da-7afaf89d9568_980x1216.png 848w, https://substackcdn.com/image/fetch/$s_!9UfK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F210afab3-f500-4b13-81da-7afaf89d9568_980x1216.png 1272w, https://substackcdn.com/image/fetch/$s_!9UfK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F210afab3-f500-4b13-81da-7afaf89d9568_980x1216.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!9UfK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F210afab3-f500-4b13-81da-7afaf89d9568_980x1216.png" width="980" height="1216" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/210afab3-f500-4b13-81da-7afaf89d9568_980x1216.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1216,&quot;width&quot;:980,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:705590,&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://newsletter.systemdesignlaws.xyz/i/222168462?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F210afab3-f500-4b13-81da-7afaf89d9568_980x1216.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_!9UfK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F210afab3-f500-4b13-81da-7afaf89d9568_980x1216.png 424w, https://substackcdn.com/image/fetch/$s_!9UfK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F210afab3-f500-4b13-81da-7afaf89d9568_980x1216.png 848w, https://substackcdn.com/image/fetch/$s_!9UfK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F210afab3-f500-4b13-81da-7afaf89d9568_980x1216.png 1272w, https://substackcdn.com/image/fetch/$s_!9UfK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F210afab3-f500-4b13-81da-7afaf89d9568_980x1216.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><h2>What Is Consistent Hashing?</h2><p><strong>Consistent hashing</strong> is a placement scheme where adding or removing one node relocates just the keys that node gains or loses, roughly 1/N of the total.</p><h3>The Ring</h3><p>Take a hash function with a large output range, such as 0 to 2^32 - 1, and wrap it into a circle. Hash each server&#8217;s identifier to get its position. Hash each key with the same function to get the key&#8217;s position.</p><h3>Lookup: Walk Clockwise</h3><p>A key belongs to the first server clockwise from its position, so each server owns the arc between its predecessor and itself. In practice this is a sorted array of server positions and a binary search for the first position at or after the key&#8217;s hash, wrapping to the start.</p><h3>What Moves on a Join or Leave</h3><p>When server D joins between A and B, it takes the keys on the arc from A to D, which used to belong to B. Every other arc keeps its owner. If D later fails, that arc falls back to B.</p><p>With N evenly loaded nodes, a join moves about 1/(N+1) of the keys and a removal about 1/N. Going from 4 to 5 servers now moves roughly 20 percent, down from 80.</p><div><hr></div><h2>Virtual Nodes</h2><h3>Why Each Server Needs More Than One Point</h3><p>Random positions split a circle unevenly. With N random points, the expected largest arc is (1 + 1/2 + ... + 1/N) / N of the ring. For N = 10 that sum is about 2.93, so the unluckiest server owns close to 3x its fair share. Failure makes it worse: a dead node&#8217;s whole arc lands on one successor, which can double that server&#8217;s load at once.</p><h3>How Virtual Nodes Fix It</h3><p>A <strong>virtual node</strong> is one of many positions a physical server occupies on the ring. In place of hashing &#8220;server-A&#8221; once, you hash &#8220;server-A#0&#8221; through &#8220;server-A#199&#8221;. The physical server owns the sum of its small arcs.</p><h3>The Math to Quote</h3><p>With N servers and V virtual nodes each, the expected share per server is still 1/N; V changes just the spread, and the average stays put. A server&#8217;s share is the sum of V small, roughly independent arcs, so its deviation from 1/N shrinks roughly as 1/sqrt(V). At V = 100 a typical server is within about 10 percent of average; at V = 1,000, about 3 percent.</p><p>Failures spread too. A dead server&#8217;s virtual nodes are scattered, so its keys flow to many successors, and each of the N - 1 survivors grows from 1/N to about 1/(N-1) of the keys.</p><p>The cost is small. Lookup is a binary search over N x V positions: 50 servers with 200 virtual nodes each is 10,000 entries, about 14 comparisons.</p><h3>Weighting Uneven Hardware</h3><p>Give a server with twice the memory twice the virtual nodes and it gets about twice the keys. Drain a node gradually by removing its virtual nodes in batches.</p><div><hr></div><h2>Replication on the Ring</h2><p>To store each key on R servers, find the owner and keep walking clockwise until you have R distinct physical servers. Skip positions belonging to a server already chosen, since adjacent virtual nodes often map to the same machine. A zone-aware walk also skips zones already used, so one zone outage costs at most one copy.</p><p>This ordered candidate list is the <strong>preference list</strong>. Quorum rules, such as write to 2 of 3 and read from 2 of 3, sit on top of it.</p><div><hr></div><h2>Operating It</h2><h3>Who Holds the Ring?</h3><p>Every router must agree on membership, or two clients will send one key to different servers. A coordination service such as ZooKeeper or etcd can hold the list, nodes can gossip it, or a proxy layer can own routing.</p><h3>Moving the Data</h3><p>The ring says who owns a key; getting the data there is a separate job. A cache can let moved keys miss and refill. A database must stream the arc to the new owner first, or read from the previous owner until the copy completes.</p><h3>Hot Keys Still Hurt</h3><p>Consistent hashing balances key counts; request rates need a separate fix. One celebrity key still maps to one owner. Cache it in-process at the app tier, or split it into suffixed copies (key#1 to key#8) spread around the ring and read a random one.</p><div><hr></div><h2>Alternatives Worth Naming</h2><ul><li><p><strong>Fixed hash slots</strong> - Hash keys into a fixed slot count, such as 16,384 in Redis Cluster, and assign slots to nodes. Pros: explicit, observable rebalancing. Cons: slot count caps how finely you can split.</p></li><li><p><strong>Rendezvous hashing</strong> - Score every node with hash(key, node) and pick the highest. Pros: minimal movement, just a node list to maintain. Cons: O(N) work per lookup.</p></li><li><p><strong>Jump consistent hash</strong> - Computes a bucket number purely from the key and the bucket count. Pros: even balance, zero memory. Cons: buckets are numbered, so you add or remove at the end.</p></li><li><p><strong>Bounded loads</strong> - Cap each node at (1 + epsilon) times the average and push overflow clockwise. Pros: limits skew. Cons: extra bookkeeping.</p></li></ul><div><hr></div><h2>When to Use in Interviews</h2><p>Reach for it in a distributed cache, a key-value store, sticky load balancing, or a chat service that pins each room to one server. Skip it when the node count is small and fixed, or a managed database already partitions for you.</p><div><hr></div><h2>Summary</h2><ul><li><p><strong>Ring over modulo</strong> - About 1/N of keys move per change, compared with N/(N+1).</p></li><li><p><strong>Virtual nodes</strong> - Share stays 1/N, spread shrinks as 1/sqrt(V).</p></li><li><p><strong>Limits</strong> - Hot keys need their own fix; membership must be agreed on.</p></li></ul><p>Practice consistent hashing by designing a distributed cache or key-value store and tracing exactly which keys move when a node joins and when one fails.</p><h2>Interview Q&amp;A</h2><ul><li><p><strong>Why the ring over hash mod N?</strong> - Changing N remaps N/(N+1) of keys, emptying a cache or forcing a near-full reshuffle. The ring moves about 1/N.</p></li><li><p><strong>How many virtual nodes?</strong> - A few hundred per server. Spread scales as 1/sqrt(V), so 100 to 200 gives roughly 7 to 10 percent deviation at trivial lookup cost.</p></li><li><p><strong>What happens when a node fails?</strong> - Its arcs pass clockwise, spread across survivors by virtual nodes; replicas already hold the data.</p></li><li><p><strong>Does it solve hot keys?</strong> - It balances keys, so hot keys need their own fix: an in-process cache or split copies.</p></li><li><p><strong>How do clients learn about changes?</strong> - From a coordination service, gossip, or a routing proxy. Version the ring so stale clients can detect it.</p></li><li><p><strong>Ring or fixed slots?</strong> - Slots make rebalancing explicit; a ring with virtual nodes lets you skip choosing a slot count upfront. Either works if you state the trade-off.</p></li></ul><p><a href="https://newsletter.systemdesignlaws.xyz">Read More Articles</a></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://newsletter.systemdesignlaws.xyz/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">SystemDesignLaws 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[AI-Assisted Commits Leak Secrets at Twice the Rate: Designing for It]]></title><description><![CDATA[What GitGuardian&#8217;s 2026 numbers mean for system design, and a four-layer answer]]></description><link>https://newsletter.systemdesignlaws.xyz/p/ai-assisted-commits-leak-secrets</link><guid isPermaLink="false">https://newsletter.systemdesignlaws.xyz/p/ai-assisted-commits-leak-secrets</guid><dc:creator><![CDATA[Jimmy Malhan]]></dc:creator><pubDate>Fri, 30 Oct 2026 16:02:46 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!BHEl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bd12d06-764b-4676-a80b-6768097df668_1024x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!BHEl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bd12d06-764b-4676-a80b-6768097df668_1024x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!BHEl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bd12d06-764b-4676-a80b-6768097df668_1024x1024.png 424w, https://substackcdn.com/image/fetch/$s_!BHEl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bd12d06-764b-4676-a80b-6768097df668_1024x1024.png 848w, https://substackcdn.com/image/fetch/$s_!BHEl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bd12d06-764b-4676-a80b-6768097df668_1024x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!BHEl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bd12d06-764b-4676-a80b-6768097df668_1024x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!BHEl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bd12d06-764b-4676-a80b-6768097df668_1024x1024.png" width="1024" height="1024" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9bd12d06-764b-4676-a80b-6768097df668_1024x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1024,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1634334,&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://newsletter.systemdesignlaws.xyz/i/222157148?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bd12d06-764b-4676-a80b-6768097df668_1024x1024.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_!BHEl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bd12d06-764b-4676-a80b-6768097df668_1024x1024.png 424w, https://substackcdn.com/image/fetch/$s_!BHEl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bd12d06-764b-4676-a80b-6768097df668_1024x1024.png 848w, https://substackcdn.com/image/fetch/$s_!BHEl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bd12d06-764b-4676-a80b-6768097df668_1024x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!BHEl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9bd12d06-764b-4676-a80b-6768097df668_1024x1024.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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>TL;DR</strong> - GitGuardian counted about 29 million new secrets on public GitHub in 2025, up 34%, with AI-service credentials up 81% and AI-assisted commits leaking at roughly double the baseline. Answer it with design: fewer long-lived secrets, scanning at every boundary, and secrets swapped out before code reaches a model.</p><blockquote><p>30-second version: &#8220;AI tools raise the volume of code and the number of places secrets travel: commits, prompts, MCP configs, logs. Treat every one of those as an egress path, give each one a control, and make credentials short-lived so any slip expires on its own.&#8221;</p></blockquote><div><hr></div><h2>The Numbers</h2><p>From GitGuardian&#8217;s State of Secrets Sprawl 2026 (published March 17, 2026, covering 2025):</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://newsletter.systemdesignlaws.xyz/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">SystemDesignLaws 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><ul><li><p><strong>About 29 million</strong> newly leaked secrets on public GitHub, up 34% year over year, the largest single-year jump the report has recorded.</p></li><li><p><strong>1,275,105 AI-service secrets</strong> leaked, up 81%.</p></li><li><p><strong>About 3.2%</strong> of commits made with Claude Code&#8217;s help leaked a secret, roughly twice the baseline. The report itself cautions that this may reflect human mistakes as much as AI behavior.</p></li><li><p><strong>24,008 unique secrets</strong> sat in the MCP configuration files it studied.</p></li><li><p><strong>64%</strong> of secrets that were valid in 2022 were still valid in 2026.</p></li><li><p>Internal repositories were about <strong>6x</strong> more likely than public ones to contain hardcoded secrets.</p></li></ul><p>The last two matter most for design. Leaks stay live until someone revokes them, and private repos need the same scanning as public ones.</p><div><hr></div><h2>How AI Tools Reshape Secret Handling</h2><p>Before coding agents, a secret leaked in roughly one way: someone committed it. Now there are four or more paths.</p><ul><li><p><strong>Commits</strong> - more code, written faster, with lighter review.</p></li><li><p><strong>Prompts</strong> - an agent reads <code>.env</code>, a config or shell output and sends it to a model provider.</p></li><li><p><strong>Tool configs</strong> - MCP servers configured with long-lived tokens in plain JSON files.</p></li><li><p><strong>Logs</strong> - gateways and observability tools that store request and response bodies (see the LiteLLM 1.107.0 compromise on October 21, 2026).</p></li></ul><p>Each path needs its own control. One pre-commit hook covers the first path.</p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Lsyl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabbadbf7-955f-4fa6-935f-b85591de2844_980x1216.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Lsyl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabbadbf7-955f-4fa6-935f-b85591de2844_980x1216.png 424w, https://substackcdn.com/image/fetch/$s_!Lsyl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabbadbf7-955f-4fa6-935f-b85591de2844_980x1216.png 848w, https://substackcdn.com/image/fetch/$s_!Lsyl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabbadbf7-955f-4fa6-935f-b85591de2844_980x1216.png 1272w, https://substackcdn.com/image/fetch/$s_!Lsyl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabbadbf7-955f-4fa6-935f-b85591de2844_980x1216.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Lsyl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabbadbf7-955f-4fa6-935f-b85591de2844_980x1216.png" width="980" height="1216" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/abbadbf7-955f-4fa6-935f-b85591de2844_980x1216.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1216,&quot;width&quot;:980,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:633983,&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://newsletter.systemdesignlaws.xyz/i/222157148?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabbadbf7-955f-4fa6-935f-b85591de2844_980x1216.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_!Lsyl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabbadbf7-955f-4fa6-935f-b85591de2844_980x1216.png 424w, https://substackcdn.com/image/fetch/$s_!Lsyl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabbadbf7-955f-4fa6-935f-b85591de2844_980x1216.png 848w, https://substackcdn.com/image/fetch/$s_!Lsyl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabbadbf7-955f-4fa6-935f-b85591de2844_980x1216.png 1272w, https://substackcdn.com/image/fetch/$s_!Lsyl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fabbadbf7-955f-4fa6-935f-b85591de2844_980x1216.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><h2>A Layered Design</h2><h3>Layer 1: Fewer secrets to leak</h3><ul><li><p><strong>Short-lived credentials.</strong> Use workload identity and OIDC for CI and cloud access, and session tokens for agents. A token that expires in an hour turns a leak into a short incident report.</p></li><li><p><strong>References over values.</strong> Configs point to a secret manager entry. MCP configs read from the environment or a keychain.</p></li></ul><h3>Layer 2: Scan at every boundary</h3><ul><li><p><strong>Pre-commit and pre-push</strong> hooks on developer machines.</p></li><li><p><strong>Server-side push protection</strong> on the repository host, because hooks can be skipped.</p></li><li><p><strong>Log pipelines</strong> scanned before persistence.</p></li></ul><h3>Layer 3: Keep secrets out of prompts</h3><p>This is the newest boundary and the one with the most room to grow. Options, in increasing strength:</p><ul><li><p><strong>Ignore files</strong> that keep the agent out of <code>.env</code> and key directories. They are easy; pair them with a scanner for secrets inside source files and command output.</p></li><li><p><strong>A local egress proxy</strong> that inspects each outbound prompt and swaps detected secrets for stand-in tokens before the request leaves the machine. The provider and every log after it see the stand-in.</p></li></ul><p>The design rule for that proxy: code identifiers can be reversed back into the answer byte-exact, but secret stand-ins must stay one-way. Reversing a secret token in model output would let a prompt injection exfiltrate it through a crafted link.</p><h3>Layer 4: Plan for a slip and contain it</h3><ul><li><p>Alert on first use of a credential from a new network or ASN.</p></li><li><p>Keep a rotation runbook that works in minutes, and rehearse it.</p></li></ul><div><hr></div><h2>How to Use This in an Interview</h2><p>When a design includes an LLM or an agent, add one box and one sentence: &#8220;Prompts pass through a local egress proxy that tokenizes secrets; the gateway logs metadata by default; agent credentials are session-scoped.&#8221; It is cheap to say and shows you treat the model call as egress.</p><div><hr></div><h2>Interview Q&amp;A</h2><ul><li><p><strong>Why is a 2x leak rate a design question more than a training question?</strong> - Volume is rising fast enough that a steady human error rate produces more leaks every year. Controls have to scale with commits, independent of headcount.</p></li><li><p><strong>Why scan private repos?</strong> - In the same report they were about 6x more likely to contain hardcoded secrets, and anyone with read access, or a stolen token, can read them.</p></li><li><p><strong>What is the weak point of pre-commit scanning?</strong> - It is optional on the client. Pair it with server-side push protection.</p></li><li><p><strong>Why one-way for secrets but reversible for identifiers?</strong> - Identifiers are needed to read the answer. Secrets stay as stand-ins in model output, because reversing them opens an exfiltration path.</p></li></ul><div><hr></div><h2>Sources</h2><ul><li><p>GitGuardian, State of Secrets Sprawl 2026: <a href="https://www.gitguardian.com/state-of-secrets-sprawl-report-2026">https://www.gitguardian.com/state-of-secrets-sprawl-report-2026</a></p></li><li><p>GitGuardian press release (March 17, 2026): <a href="https://blog.gitguardian.com/the-state-of-secrets-sprawl-2026-pr/">https://blog.gitguardian.com/the-state-of-secrets-sprawl-2026-pr/</a></p></li><li><p>Cloud Security Alliance, LiteLLM 1.107.0 research note: <a href="https://labs.cloudsecurityalliance.org/research/csa-research-note-litellm-1107-gateway-log-token-compromise/">https://labs.cloudsecurityalliance.org/research/csa-research-note-litellm-1107-gateway-log-token-compromise/</a></p></li></ul><div><hr></div><p><em>Disclosure: I build <a href="https://pretense.ai/?utm_source=substack&amp;utm_medium=newsletter&amp;utm_campaign=sdl-secrets-sprawl-2026">Pretense</a>, the local egress proxy described in layer 3. It swaps API keys, tokens and code identifiers for stand-ins before a prompt leaves the laptop, restores identifiers byte-exact in the answer, and keeps secrets as stand-ins. By default it flags emails and phone numbers for review.</em></p><p><a href="https://newsletter.systemdesignlaws.xyz">Read More Articles</a></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://newsletter.systemdesignlaws.xyz/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">SystemDesignLaws 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[Your AI Gateway Logs Are a Credential Store]]></title><description><![CDATA[What the LiteLLM 1.107.0 compromise teaches about logging prompts, and four fixes, cheapest first]]></description><link>https://newsletter.systemdesignlaws.xyz/p/your-ai-gateway-logs-are-a-credential</link><guid isPermaLink="false">https://newsletter.systemdesignlaws.xyz/p/your-ai-gateway-logs-are-a-credential</guid><dc:creator><![CDATA[Jimmy Malhan]]></dc:creator><pubDate>Tue, 27 Oct 2026 16:02:34 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!kyWn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77d7d29b-aa25-4d33-9508-e3d8e1c88d65_1092x1092.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!kyWn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77d7d29b-aa25-4d33-9508-e3d8e1c88d65_1092x1092.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!kyWn!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77d7d29b-aa25-4d33-9508-e3d8e1c88d65_1092x1092.png 424w, https://substackcdn.com/image/fetch/$s_!kyWn!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77d7d29b-aa25-4d33-9508-e3d8e1c88d65_1092x1092.png 848w, https://substackcdn.com/image/fetch/$s_!kyWn!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77d7d29b-aa25-4d33-9508-e3d8e1c88d65_1092x1092.png 1272w, https://substackcdn.com/image/fetch/$s_!kyWn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77d7d29b-aa25-4d33-9508-e3d8e1c88d65_1092x1092.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!kyWn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77d7d29b-aa25-4d33-9508-e3d8e1c88d65_1092x1092.png" width="1092" height="1092" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/77d7d29b-aa25-4d33-9508-e3d8e1c88d65_1092x1092.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1092,&quot;width&quot;:1092,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1740493,&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://newsletter.systemdesignlaws.xyz/i/222154426?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77d7d29b-aa25-4d33-9508-e3d8e1c88d65_1092x1092.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_!kyWn!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77d7d29b-aa25-4d33-9508-e3d8e1c88d65_1092x1092.png 424w, https://substackcdn.com/image/fetch/$s_!kyWn!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77d7d29b-aa25-4d33-9508-e3d8e1c88d65_1092x1092.png 848w, https://substackcdn.com/image/fetch/$s_!kyWn!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77d7d29b-aa25-4d33-9508-e3d8e1c88d65_1092x1092.png 1272w, https://substackcdn.com/image/fetch/$s_!kyWn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77d7d29b-aa25-4d33-9508-e3d8e1c88d65_1092x1092.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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>TL;DR</strong> - On October 21, 2026, attackers published a poisoned LiteLLM 1.107.0 using GitHub tokens that LiteLLM believes leaked through its own AI gateway logs. The lesson is architectural: any box that records prompts and responses records whatever secrets ride inside them. Swap secrets before they leave the laptop, log metadata by default, and keep agent tokens short-lived.</p><blockquote><p>30-second version: &#8220;An AI gateway sees every prompt and every answer. If it logs bodies, its log store holds every credential an engineer or agent ever pasted, and it needs the same protection as a vault. Better: keep real secrets on the laptop so the gateway sees stand-ins every time.&#8221;</p></blockquote><div><hr></div><h2>What Happened</h2><p>LiteLLM is a popular open-source gateway that sits between applications and model providers. According to the Cloud Security Alliance research note published October 23:</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://newsletter.systemdesignlaws.xyz/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">SystemDesignLaws 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><ul><li><p><strong>The release:</strong> malicious <code>litellm==1.107.0</code> builds reached PyPI, Docker Hub and GHCR on October 21. The PyPI window was roughly 11:39 to 13:23 UTC. Wiz counted about 49,000 downloads.</p></li><li><p><strong>The access:</strong> the attacker used stolen GitHub CLI OAuth tokens belonging to three LiteLLM engineers. One token was used to override branch protection, one to approve the release, and one to delete workflow records afterward.</p></li><li><p><strong>The suspected leak path:</strong> an internet-exposed internal LiteLLM deployment had been logging request and response bodies from coding-agent sessions. LiteLLM reports cases where GitHub CLI tokens ended up inside those bodies, and so inside the logs. This is LiteLLM&#8217;s working explanation; the root-cause review is still open.</p></li><li><p><strong>The payload:</strong> files that run on every Python start and collect cloud, Kubernetes, SSH, registry and AI-provider credentials, then send them to a lookalike domain.</p></li></ul><div><hr></div><h2>The Design Flaw: Logging Bodies at a Chokepoint</h2><p><strong>What is an AI gateway?</strong> A proxy in front of model providers that handles routing, keys, quotas, cost tracking and, often, logging. It is the AI version of an API gateway, and it inherits the same habit: log everything for debugging.</p><p>That habit is where the exposure starts. A coding agent&#8217;s traffic is richer than ordinary API traffic. It carries:</p><ul><li><p>File contents, including <code>.env</code> files and config the agent opened.</p></li><li><p>Shell output, including tokens a command printed.</p></li><li><p>Tool results, including credentials a tool fetched.</p></li></ul><p>Log those bodies and the log store becomes the richest credential collection in the company: searchable, replicated to backups, and it deserves the same guard as the secret manager.</p><p>The CSA note&#8217;s own recommendation states it plainly: treat gateway logs like a secret store and make content logging a reviewed exception.</p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cRp2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4fa03fb-cb9b-4b6c-8fb3-c3d8b693d202_980x1216.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cRp2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4fa03fb-cb9b-4b6c-8fb3-c3d8b693d202_980x1216.png 424w, https://substackcdn.com/image/fetch/$s_!cRp2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4fa03fb-cb9b-4b6c-8fb3-c3d8b693d202_980x1216.png 848w, https://substackcdn.com/image/fetch/$s_!cRp2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4fa03fb-cb9b-4b6c-8fb3-c3d8b693d202_980x1216.png 1272w, https://substackcdn.com/image/fetch/$s_!cRp2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4fa03fb-cb9b-4b6c-8fb3-c3d8b693d202_980x1216.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!cRp2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4fa03fb-cb9b-4b6c-8fb3-c3d8b693d202_980x1216.png" width="980" height="1216" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a4fa03fb-cb9b-4b6c-8fb3-c3d8b693d202_980x1216.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1216,&quot;width&quot;:980,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:608242,&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://newsletter.systemdesignlaws.xyz/i/222154426?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4fa03fb-cb9b-4b6c-8fb3-c3d8b693d202_980x1216.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_!cRp2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4fa03fb-cb9b-4b6c-8fb3-c3d8b693d202_980x1216.png 424w, https://substackcdn.com/image/fetch/$s_!cRp2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4fa03fb-cb9b-4b6c-8fb3-c3d8b693d202_980x1216.png 848w, https://substackcdn.com/image/fetch/$s_!cRp2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4fa03fb-cb9b-4b6c-8fb3-c3d8b693d202_980x1216.png 1272w, https://substackcdn.com/image/fetch/$s_!cRp2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4fa03fb-cb9b-4b6c-8fb3-c3d8b693d202_980x1216.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><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" class="icon-noB79L"><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><h2>Four Fixes, Cheapest First</h2><h3>1. Log metadata by default</h3><p>Record model, token counts, latency, user and cost. Turn body logging off by default. When someone needs bodies to debug, turn it on for one user for one hour, and then turn it off again.</p><h3>2. Rotate what may already be there</h3><p>If any gateway, proxy or observability tool stored agent request or response bodies, search those stores and their backups for token prefixes (<code>ghp_</code>, <code>gho_</code>, <code>sk-</code>, <code>AKIA</code>) and revoke every hit. A 2026 GitGuardian study found 64% of secrets that were valid in 2022 were still valid in 2026, so plan to revoke each one yourself.</p><h3>3. Shrink token lifetime</h3><p>An OAuth token that lives for months turns one log line into months of access. Give agent sessions short-lived, narrowly scoped tokens, and move releases to trusted publishing so the CI pipeline is the one path that ships a package.</p><h3>4. Swap secrets before they leave the machine</h3><p>The strongest control moves the fix upstream of every log: the gateway stores exactly what it receives, so send it stand-ins. Run a local proxy on the developer laptop that replaces detected secrets with stand-in tokens before the request leaves. The gateway, the provider and every log downstream then hold the stand-in.</p><p>Two details keep everything working:</p><ul><li><p><strong>Reversible where it is safe.</strong> Code identifiers can be swapped back byte-exact in the answer, so the developer reads their own code.</p></li><li><p><strong>One-way for secrets.</strong> Secret stand-ins stay as stand-ins in model output. If a prompt injection gets the model to echo a stand-in into a link, reversing it would hand the real credential to the attacker.</p></li></ul><div><hr></div><h2>Where This Shows Up in a System Design Interview</h2><p>Any design with an LLM in it now has an egress question. Draw the gateway, then say three things:</p><ul><li><p>Logs hold metadata by default.</p></li><li><p>Secrets are tokenized client-side, before the gateway.</p></li><li><p>Agent credentials are short-lived and scoped per session.</p></li></ul><p>That is one sentence each and it signals you have read the 2026 incident reports.</p><div><hr></div><h2>Interview Q&amp;A</h2><ul><li><p><strong>Why swap on the client, ahead of the gateway?</strong> - Scrubbing inside the gateway happens after it has received the secrets, which can still surface in memory dumps, crash reports or a stray log path. Swapping on the client means stand-ins are all that arrive.</p></li><li><p><strong>Is logging prompts ever justified?</strong> - Yes, for evaluation and abuse review. Store them encrypted, with short retention and access logging, and scan for credentials before persisting.</p></li><li><p><strong>What is the blast radius of one leaked GitHub OAuth token?</strong> - Everything that token&#8217;s user can do, which in this incident included approving a production release.</p></li><li><p><strong>How would you detect this kind of compromise?</strong> - Alert on releases outside the normal pipeline, on branch-protection overrides, and on deleted workflow runs.</p></li></ul><div><hr></div><h2>Sources</h2><ul><li><p>Cloud Security Alliance, research note on the LiteLLM 1.107.0 compromise (October 23, 2026): <a href="https://labs.cloudsecurityalliance.org/research/csa-research-note-litellm-1107-gateway-log-token-compromise/">https://labs.cloudsecurityalliance.org/research/csa-research-note-litellm-1107-gateway-log-token-compromise/</a></p></li><li><p>GitGuardian, State of Secrets Sprawl 2026: <a href="https://www.gitguardian.com/state-of-secrets-sprawl-report-2026">https://www.gitguardian.com/state-of-secrets-sprawl-report-2026</a></p></li></ul><div><hr></div><p><em>Disclosure: I build <a href="https://pretense.ai/?utm_source=substack&amp;utm_medium=newsletter&amp;utm_campaign=sdl-ai-gateway-logs">Pretense</a>, a local proxy that does fix 4: it swaps API keys, tokens (including GitHub </em><code>gho_</code><em>/</em><code>ghp_</code><em> tokens) and code identifiers for stand-ins before a request leaves the laptop. Identifiers come back byte-exact; secrets stay as stand-ins in the reply. It does its job when it runs in front of the gateway, and it works alongside fixes 1 to 3.</em></p><p><a href="https://newsletter.systemdesignlaws.xyz">Read More Articles</a></p><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://newsletter.systemdesignlaws.xyz/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">SystemDesignLaws 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[Real-time Updates]]></title><description><![CDATA[- Real-time systems need two hops: server to client (WebSockets, SSE, long polling) and source to server (Pub/Su...]]></description><link>https://newsletter.systemdesignlaws.xyz/p/real-time-updates</link><guid isPermaLink="false">https://newsletter.systemdesignlaws.xyz/p/real-time-updates</guid><dc:creator><![CDATA[Jimmy Malhan]]></dc:creator><pubDate>Mon, 16 Mar 2026 17:39:24 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!gRdd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3867759c-9e8b-422c-ac3b-a61cf27c9528_1840x644.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="pullquote"><p>30-second elevator pitch: "Real-time updates require efficient push channels. I choose based on latency needs: polling for 2-5 second updates, long polling or SSE for near real-time, WebSockets when I need bidirectional low latency. The second hop is Pub/Sub or consistent hashing to fan out updates from the source to servers."</p></div><h2>The Problem</h2><p>Consider a colla&#8230;</p>
      <p>
          <a href="https://newsletter.systemdesignlaws.xyz/p/real-time-updates">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Multi-step Processes]]></title><description><![CDATA[- Multi-step processes fail halfway: payment charged but inventory not reserved. Use workflow engines like Tempo...]]></description><link>https://newsletter.systemdesignlaws.xyz/p/multi-step-processes</link><guid isPermaLink="false">https://newsletter.systemdesignlaws.xyz/p/multi-step-processes</guid><dc:creator><![CDATA[Jimmy Malhan]]></dc:creator><pubDate>Mon, 16 Mar 2026 17:39:20 GMT</pubDate><enclosure url="https://raw.githubusercontent.com/jimmymalhan/systemdesignlaws.xyz/feature/newsletter-agent-system/newsletter/plots/svg/ms-order-fulfillment.svg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="pullquote"><p>30-second elevator pitch: "Multi-step processes fail halfway - payment charged but inventory not reserved. I use workflow engines like Temporal or AWS Step Functions so each step is durable, failures trigger retries or compensation, and the system picks up exactly where it left off after a crash."</p></div><h2>What You Will Learn</h2><blockquote><p><strong>Approaches</strong></p></blockquote><blockquote><p>- Single-server orchestratio&#8230;</p></blockquote>
      <p>
          <a href="https://newsletter.systemdesignlaws.xyz/p/multi-step-processes">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Dealing with Contention]]></title><description><![CDATA[- Fix race conditions with atomicity, locks, or optimistic concurrency. Scale to distributed coordination when m...]]></description><link>https://newsletter.systemdesignlaws.xyz/p/dealing-with-contention</link><guid isPermaLink="false">https://newsletter.systemdesignlaws.xyz/p/dealing-with-contention</guid><dc:creator><![CDATA[Jimmy Malhan]]></dc:creator><pubDate>Mon, 16 Mar 2026 17:39:16 GMT</pubDate><enclosure url="https://raw.githubusercontent.com/jimmymalhan/systemdesignlaws.xyz/feature/newsletter-agent-system/newsletter/plots/svg/dc-race-condition.svg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="pullquote"><p>30-second elevator pitch: "Contention happens when two users act on the same data at once, like two people buying the last concert ticket. I fix it by making operations atomic, using locks when conflicts are common, or optimistic concurrency when they are rare. For distributed systems, I use sagas or two-phase commit. I always exhaust single-database so&#8230;</p></div>
      <p>
          <a href="https://newsletter.systemdesignlaws.xyz/p/dealing-with-contention">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Caching for System Design Interviews]]></title><description><![CDATA[- Caching cuts latency 50x and reduces DB load by 95%+. Cache-aside with Redis is the default. Layer CDN for glo...]]></description><link>https://newsletter.systemdesignlaws.xyz/p/caching-for-system-design-interviews</link><guid isPermaLink="false">https://newsletter.systemdesignlaws.xyz/p/caching-for-system-design-interviews</guid><dc:creator><![CDATA[Jimmy Malhan]]></dc:creator><pubDate>Mon, 16 Mar 2026 17:39:12 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!4eGo!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F53bfac2b-c99b-4324-9df4-9063e7c58acd_1600x900.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="pullquote"><p>30-second elevator pitch: "Caching stores frequently accessed data in memory so reads skip the database. I start with cache-aside using Redis as the default, add CDN for global static assets, and choose invalidation strategy based on freshness requirements. Cache-aside handles most scenarios, and I layer additional strategies only when the problem deman&#8230;</p></div>
      <p>
          <a href="https://newsletter.systemdesignlaws.xyz/p/caching-for-system-design-interviews">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Managing Long-Running Tasks]]></title><description><![CDATA[- When a task takes more than a few seconds, do not make the client wait. Accept the request immediately (return...]]></description><link>https://newsletter.systemdesignlaws.xyz/p/managing-long-running-tasks</link><guid isPermaLink="false">https://newsletter.systemdesignlaws.xyz/p/managing-long-running-tasks</guid><dc:creator><![CDATA[Jimmy Malhan]]></dc:creator><pubDate>Mon, 16 Mar 2026 17:38:59 GMT</pubDate><enclosure url="https://raw.githubusercontent.com/jimmymalhan/systemdesignlaws.xyz/feature/newsletter-agent-system/newsletter/plots/svg/lt-sync-vs-async.svg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="pullquote"><p>30-second elevator pitch: "For any operation that takes more than a few seconds, I return a job ID immediately and process asynchronously. A message queue decouples submission from processing. Workers pull jobs, execute them, and update status. The client polls for completion or gets a webhook callback. I add exponential backoff for retries and a dead l&#8230;</p></div>
      <p>
          <a href="https://newsletter.systemdesignlaws.xyz/p/managing-long-running-tasks">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Handling Large Blobs]]></title><description><![CDATA[- Files should never pass through your application server. Use presigned URLs for direct upload to object storag...]]></description><link>https://newsletter.systemdesignlaws.xyz/p/handling-large-blobs</link><guid isPermaLink="false">https://newsletter.systemdesignlaws.xyz/p/handling-large-blobs</guid><dc:creator><![CDATA[Jimmy Malhan]]></dc:creator><pubDate>Mon, 16 Mar 2026 17:38:55 GMT</pubDate><enclosure url="https://raw.githubusercontent.com/jimmymalhan/systemdesignlaws.xyz/feature/newsletter-agent-system/newsletter/plots/svg/lb-naive-upload.svg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="pullquote"><p>30-second elevator pitch: "Large files bypass my application server entirely. Clients get a presigned URL and upload directly to S3 in chunks. An S3 event triggers async processing like thumbnails or transcoding. Downloads go through a CDN. My server only handles metadata and authorization."</p></div><h2>What You Will Learn</h2><blockquote><p><strong>Upload Patterns</strong></p></blockquote><blockquote><p>- Presigned URL upload (bypas&#8230;</p></blockquote>
      <p>
          <a href="https://newsletter.systemdesignlaws.xyz/p/handling-large-blobs">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Scaling Writes]]></title><description><![CDATA[- Scale writes in four tiers: vertical scaling with write-optimized databases, sharding to spread load, queues a...]]></description><link>https://newsletter.systemdesignlaws.xyz/p/scaling-writes</link><guid isPermaLink="false">https://newsletter.systemdesignlaws.xyz/p/scaling-writes</guid><dc:creator><![CDATA[Jimmy Malhan]]></dc:creator><pubDate>Mon, 16 Mar 2026 17:38:36 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!IrHs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d911796-4d50-4f9e-8e43-b382473622b9_1600x746.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="pullquote"><p>30-second elevator pitch: "Write scaling is harder than read scaling because every write must persist to disk. I exhaust vertical scaling and database tuning first. Then I shard by partition key to spread load linearly. For bursty traffic I add queues and load shedding. For extreme volume I batch writes and use hierarchical aggregation. Each tier builds&#8230;</p></div>
      <p>
          <a href="https://newsletter.systemdesignlaws.xyz/p/scaling-writes">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Scaling Reads]]></title><description><![CDATA[- Reads dominate writes 100:1. Scale in three tiers: optimize the database (indexing, denormalization), scale ho...]]></description><link>https://newsletter.systemdesignlaws.xyz/p/scaling-reads</link><guid isPermaLink="false">https://newsletter.systemdesignlaws.xyz/p/scaling-reads</guid><dc:creator><![CDATA[Jimmy Malhan]]></dc:creator><pubDate>Mon, 16 Mar 2026 17:38:14 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!zYnC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a1772f1-0e56-4c84-8f54-6a182f740181_1600x746.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="pullquote"><p>30-second elevator pitch: "Read traffic grows exponentially faster than writes. I handle this in three tiers: first optimize the existing database with indexes and denormalization, then scale horizontally with read replicas, and finally add caching layers. Each tier builds on the previous one, and I always start with the simplest solution."</p></div><h2>The Problem</h2><p>Co&#8230;</p>
      <p>
          <a href="https://newsletter.systemdesignlaws.xyz/p/scaling-reads">
              Read more
          </a>
      </p>
   ]]></content:encoded></item></channel></rss>