<?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[slys.dev]]></title><description><![CDATA[Ever wondered how Uber’s ride matching happens in seconds, why Instagram’s feed feels like it reads your mind, or how OpenAI’s chat models can hold conversations just like us? Subscribe to our blog and unravel these secrets together!]]></description><link>https://iam.slys.dev</link><image><url>https://substackcdn.com/image/fetch/$s_!9q0E!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3b67508-e73c-434b-89ae-fde2c72e8fa4_256x256.png</url><title>slys.dev</title><link>https://iam.slys.dev</link></image><generator>Substack</generator><lastBuildDate>Tue, 07 Apr 2026 05:48:50 GMT</lastBuildDate><atom:link href="https://iam.slys.dev/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Anna & Jakub Slys]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[jakub@slys.dev]]></webMaster><itunes:owner><itunes:email><![CDATA[jakub@slys.dev]]></itunes:email><itunes:name><![CDATA[Jakub Slys 🤖]]></itunes:name></itunes:owner><itunes:author><![CDATA[Jakub Slys 🤖]]></itunes:author><googleplay:owner><![CDATA[jakub@slys.dev]]></googleplay:owner><googleplay:email><![CDATA[jakub@slys.dev]]></googleplay:email><googleplay:author><![CDATA[Jakub Slys 🤖]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Thinking clearly in interviews — Longest Substring Without Repeating Characters]]></title><description><![CDATA[Understanding the why before the code (Rust &#183; Python &#183; Scala)]]></description><link>https://iam.slys.dev/p/thinking-clearly-in-interviews-longest</link><guid isPermaLink="false">https://iam.slys.dev/p/thinking-clearly-in-interviews-longest</guid><dc:creator><![CDATA[Jakub Slys 🤖]]></dc:creator><pubDate>Mon, 30 Mar 2026 21:28:42 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Dzji!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F867dd58b-6bc9-4163-9331-b847a489b7d7_1536x1024.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_!Dzji!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F867dd58b-6bc9-4163-9331-b847a489b7d7_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Dzji!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F867dd58b-6bc9-4163-9331-b847a489b7d7_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Dzji!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F867dd58b-6bc9-4163-9331-b847a489b7d7_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Dzji!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F867dd58b-6bc9-4163-9331-b847a489b7d7_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Dzji!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F867dd58b-6bc9-4163-9331-b847a489b7d7_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Dzji!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F867dd58b-6bc9-4163-9331-b847a489b7d7_1536x1024.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/867dd58b-6bc9-4163-9331-b847a489b7d7_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2892303,&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://iam.slys.dev/i/187834348?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F867dd58b-6bc9-4163-9331-b847a489b7d7_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Dzji!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F867dd58b-6bc9-4163-9331-b847a489b7d7_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Dzji!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F867dd58b-6bc9-4163-9331-b847a489b7d7_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Dzji!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F867dd58b-6bc9-4163-9331-b847a489b7d7_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Dzji!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F867dd58b-6bc9-4163-9331-b847a489b7d7_1536x1024.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 role="img" 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><title></title><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>&#9888;&#65039; Before we dive in &#8212; a recommendation for makers and builders</strong></p><div class="embedded-publication-wrap" data-attrs="{&quot;id&quot;:3053309,&quot;name&quot;:&quot;The Founders Corner&#174;&quot;,&quot;logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!3lwY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1007f51a-8c4c-425f-bda5-da428bc29120_1024x1024.png&quot;,&quot;base_url&quot;:&quot;https://www.the-founders-corner.com&quot;,&quot;hero_text&quot;:&quot;Your weekly BOOST to Raise and Grow Like A Pro. Tips and Techniques used by prolific Founders.\n&quot;,&quot;author_name&quot;:&quot;Ruben Dominguez&quot;,&quot;show_subscribe&quot;:true,&quot;logo_bg_color&quot;:&quot;#fafafa&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="EmbeddedPublicationToDOMWithSubscribe"><div class="embedded-publication show-subscribe"><a class="embedded-publication-link-part" native="true" href="https://www.the-founders-corner.com?utm_source=substack&amp;utm_campaign=publication_embed&amp;utm_medium=web"><img class="embedded-publication-logo" src="https://substackcdn.com/image/fetch/$s_!3lwY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1007f51a-8c4c-425f-bda5-da428bc29120_1024x1024.png" width="56" height="56" style="background-color: rgb(250, 250, 250);"><span class="embedded-publication-name">The Founders Corner&#174;</span><div class="embedded-publication-hero-text">Your weekly BOOST to Raise and Grow Like A Pro. Tips and Techniques used by prolific Founders.
</div><div class="embedded-publication-author-name">By Ruben Dominguez</div></a><form class="embedded-publication-subscribe" method="GET" action="https://www.the-founders-corner.com/subscribe?"><input type="hidden" name="source" value="publication-embed"><input type="hidden" name="autoSubmit" value="true"><input type="email" class="email-input" name="email" placeholder="Type your email..."><input type="submit" class="button primary" value="Subscribe"></form></div></div><p><em><strong>The Founders Corner&#174;</strong></em> by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Chris Tottman&quot;,&quot;id&quot;:4208729,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!dFRK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c896550-de04-4929-9967-52d09137f397_380x380.jpeg&quot;,&quot;uuid&quot;:&quot;dd85361a-e953-4090-902c-cf3ec543115c&quot;}" data-component-name="MentionToDOM"></span> is one of the most practical founder newsletters out there. He writes about turning big ambition into repeatable execution, using frameworks like OKRs and SMART goals, and helping founders think clearly rather than grind blindly.</p><div><hr></div><p>You&#8217;re walking through a busy farmers market with a friend. You agree on a simple rule: &#8220;<em>Let&#8217;s only buy one of each item</em>&#8221;. It sounds easy - until you realize how quickly your basket becomes a messy history of decisions. You pick up apples, then bread, then cheese&#8230; and a few stalls later you see apples again. You&#8217;re not doing anything wrong; you just forgot that apples were already in the basket.</p><p>So you pause. You don&#8217;t dump everything and start over. You don&#8217;t keep walking pretending the duplicate doesn&#8217;t exist. You do something more practical: you look back to the point where apples first showed up, and you adjust your plan so that your &#8220;<em>current run of unique items</em>&#8221; starts after that. Your basket still contains the past, but your <em>current constraint</em> (&#8220;<em>no duplicates</em>&#8221;) applies only to the window of choices you&#8217;re actively considering.</p><p>That little moment - realizing you&#8217;re carrying history, but you only need to reason about a moving slice of it - is a surprisingly good model for how a lot of interview problems work. Nothing is broken. The confusion comes from trying to track &#8220;<em>everything so far</em>&#8221; when the problem only cares about the best <em>contiguous stretch</em> that satisfies a rule.</p><blockquote><p><strong>Problem</strong></p><p>Given a string, find the length of the longest substring without repeating characters.</p><p><strong>Examples</strong></p><p>Example 1:</p><p>Input: <code>&#8220;abcabcbb&#8221;</code></p><p>Output: 3</p><p>Explanation: The answer is <code>&#8220;abc&#8221;</code>, with the length of 3.</p><p>Example 2:</p><p>Input: <code>&#8220;bbbbb&#8221;</code></p><p>Output: 1</p><p>Explanation: The answer is <code>&#8220;b&#8221;</code>, with the length of 1.</p><p>Example 3:</p><p>Input: <code>&#8220;pwwkew&#8221;</code></p><p>Output: 3</p><p>Explanation: The answer is <code>&#8220;wke&#8221;</code>, with the length of 3.</p><p>Note that the answer must be a substring, <code>&#8220;pwke&#8221;</code> is a subsequence and not a substring.</p><p><strong>Constraints</strong></p><ul><li><p><em>No explicit constraints found in extracted text.</em></p></li></ul></blockquote><p>This is exactly the mindset behind finding the longest substring with no repeating characters: keep a clean, up-to-date &#8220;<em>current window</em>&#8221;, and when a repeat appears, move the start forward intelligently rather than rebuilding from scratch.</p><h1>&#127897;&#65039; Why interviewers like this problem</h1><p>This problem looks simple on the surface: &#8220;<em>scan a string and find the longest stretch without repeats</em>&#8221;. But interviewers aren&#8217;t really testing whether you can write a loop. They&#8217;re testing whether you can manage state under pressure, explain an invariant, and avoid subtle off-by-one errors when the input fights back.</p><p>A strong solution requires you to recognize a classic pattern: a <strong>sliding window</strong> where the &#8220;<em>valid region</em>&#8221; expands and contracts as you scan. That pattern appears everywhere: rate limiting, caching, deduplication, streaming analytics, log processing, and even UI behaviors like &#8220;<em>longest recent sequence without repeating events</em>&#8221;.</p><p>From an interviewer&#8217;s perspective, this question reveals:</p><ul><li><p><strong>Whether you can translate an English requirement into a precise invariant.</strong> What does &#8220;<em>substring</em>&#8221; mean operationally? What counts as &#8220;<em>repeating</em>&#8221;? What does the window represent at every moment?</p></li><li><p><strong>Whether you can optimize with intent.</strong> Many candidates start with a brute force approach and either get stuck or optimize blindly. The best candidates can say: &#8220;<em>This is quadratic because we restart work; we need to avoid re-scanning</em>&#8221;.</p></li><li><p><strong>Whether you can communicate while coding.</strong> The optimal solution is not long, but it&#8217;s easy to get wrong if you can&#8217;t narrate what each pointer means.</p></li><li><p><strong>Whether you handle edge cases calmly.</strong> Empty string, repeated characters early, repeated characters far apart, and strings with mixed character sets all stress the details.</p></li></ul><p>It&#8217;s also a good &#8220;<em>live coding</em>&#8221; prompt because it&#8217;s small enough to finish, but rich enough to show how you think.</p><h1>&#128214; Understanding the problem in plain language</h1><p>You&#8217;re given a string. You want the length of the longest contiguous chunk (a substring) where every character appears at most once inside that chunk.</p><p>&#8220;<em>Contiguous</em>&#8221; is the whole point. You&#8217;re not allowed to skip characters. If the string is <code>"pwwkew"</code>, the characters <code>p-w-k-e</code> exist in order, but not as one continuous slice, so that doesn&#8217;t count.</p><p>So the output is a single integer: the maximum length among all substrings that contain no duplicates.</p><p>There are a few clarifications worth saying out loud in an interview:</p><ul><li><p>We&#8217;re looking for <strong>length</strong>, not the substring itself (though you can often extend the solution to return the substring).</p></li><li><p>Characters are considered repeating <strong>within the substring</strong>, not across the whole string.</p></li><li><p>The best substring can start and end anywhere. It doesn&#8217;t have to align with word boundaries or anything &#8220;<em>semantic</em>&#8221;.</p></li><li><p>We should assume the string can be reasonably large unless told otherwise - large enough that an obviously quadratic solution will time out or be frowned upon.</p></li></ul><p>If constraints aren&#8217;t provided (as in many prompts), it&#8217;s fair to ask: &#8220;<em>Should I assume the string can be up to, say, 100k characters?</em>&#8221; Interviewers will usually say yes, and that immediately pushes you toward an <code>O(n)</code> solution.</p><h1>&#128099; Reasoning through examples</h1><p>Let&#8217;s walk through <code>"abcabcbb"</code> slowly, the way you&#8217;d narrate it on a whiteboard.</p><p>You start at the first character:</p><ul><li><p>Consider <code>"a"</code>: valid, length 1</p></li><li><p>Extend to <code>"ab"</code>: still valid, length 2</p></li><li><p>Extend to <code>"abc"</code>: still valid, length 3</p></li></ul><p>Now you try to extend with the next character, which is <code>"a"</code> again. If you naively keep growing, you&#8217;d have <code>"abca"</code>, which is invalid because <code>a</code> repeats.</p><p>Here&#8217;s the key interview moment: what do you do when you hit a repeat?</p><p>A weaker approach is: &#8220;<em>Start over from the next character</em>&#8221;. That leads to lots of repeated scanning.</p><p>A stronger approach is: &#8220;<em>I already know where the previous </em><code>a</code><em> was. The longest valid substring ending here must start after that previous </em><code>a</code>&#8221;. So instead of restarting from scratch, you slide the start pointer forward to exclude the earlier <code>a</code>.</p><p>So for <code>"abcabcbb"</code>:</p><ul><li><p>When you hit the second <code>a</code> (at index 3), you move the start to index 1 (right after the previous <code>a</code> at index 0).</p></li><li><p>Your window becomes <code>"bca"</code> (indices 1..3), length 3.</p></li><li><p>Then you see <code>b</code> again, slide start to after the previous <code>b</code>, and so on.</p></li></ul><p>You keep a running best: it stays 3.</p><p>Now consider <code>"bbbbb"</code>:</p><ul><li><p>Start with <code>"b"</code>, length 1.</p></li><li><p>Next <code>b</code> repeats immediately. The best valid substring ending here is still length 1, because the window collapses to just <code>"b"</code> each time.</p></li></ul><p>And <code>"pwwkew"</code> is the example where intuition often fails:</p><ul><li><p>You see <code>"p"</code>, then <code>"pw"</code>, then <code>"pww"</code> becomes invalid at the second <code>w</code>.</p></li><li><p>Sliding the start past the first <code>w</code> gives you <code>"w"</code> (not <code>"pw"</code> - because you must keep contiguity).</p></li><li><p>Then you extend: <code>"wk"</code>, <code>"wke"</code>, length 3.</p></li></ul><p>A strong candidate explicitly distinguishes &#8220;<em>contiguous substring</em>&#8221; from &#8220;<em>subsequence</em>&#8221; while narrating this. Interviewers love that, because it shows you&#8217;re reading carefully.</p><h1>&#128207; Constraints and what they tell us</h1><p>When constraints are missing, you have to infer what the interviewer expects. This is a real interview skill: <em>use the shape of the problem</em> to pick an approach, and confirm assumptions verbally.</p><p>There are usually three regimes:</p><ul><li><p>If the string length is tiny (say, under a few thousand), you can get away with <code>O(n&#178;) </code>brute force. But that&#8217;s rarely the intent in a top-tier interview, because it doesn&#8217;t test much beyond nested loops.</p></li><li><p>If the string length is moderate to large (tens of thousands or more), <code>O(n&#178;) </code>becomes risky. A 100k string would be catastrophic with a quadratic approach.</p></li><li><p>If the character set is small and known (e.g., ASCII), you can optimize further using fixed-size arrays. If it&#8217;s general Unicode, you typically use a hash map.</p></li></ul><p>So what should you say out loud?</p><ul><li><p>&#8220;<em>If the string can be large, we should aim for </em><code>O(n)</code>&#8221;.</p></li><li><p>&#8220;<em>We can do that with a sliding window and a map of last-seen positions</em>&#8221;.</p></li><li><p>&#8220;<em>Space is </em><code>O(min(n, alphabet_size))</code><em> because we store at most one entry per distinct character in the window</em>&#8221;.</p></li></ul><p>Interviewers want to see you connect constraints to design choices. Even if the prompt doesn&#8217;t include them, your reasoning should.</p><h1>&#129300; The obvious first idea &#8212; and why it&#8217;s not enough</h1><p>The natural first idea is brute force:</p><ul><li><p>Enumerate every possible start index <code>i</code>.</p></li><li><p>From <code>i</code>, expand <code>j</code> forward until you hit a repeated character.</p></li><li><p>Track the maximum length.</p></li></ul><p>To detect repeats, you keep a set of seen characters as you expand <code>j</code>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fW6h!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2190af07-dc73-4ed2-a5e0-e677238438d2_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fW6h!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2190af07-dc73-4ed2-a5e0-e677238438d2_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!fW6h!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2190af07-dc73-4ed2-a5e0-e677238438d2_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!fW6h!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2190af07-dc73-4ed2-a5e0-e677238438d2_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!fW6h!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2190af07-dc73-4ed2-a5e0-e677238438d2_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fW6h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2190af07-dc73-4ed2-a5e0-e677238438d2_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2190af07-dc73-4ed2-a5e0-e677238438d2_1536x1024.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;:329512,&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://iam.slys.dev/i/187834348?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2190af07-dc73-4ed2-a5e0-e677238438d2_1536x1024.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_!fW6h!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2190af07-dc73-4ed2-a5e0-e677238438d2_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!fW6h!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2190af07-dc73-4ed2-a5e0-e677238438d2_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!fW6h!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2190af07-dc73-4ed2-a5e0-e677238438d2_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!fW6h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2190af07-dc73-4ed2-a5e0-e677238438d2_1536x1024.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 role="img" 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><title></title><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>This feels good because it matches how humans reason about substrings: &#8220;<em>Try starting here, grow until it breaks</em>&#8221;.</p><p>But the performance is the issue. In the worst case - like a string of all distinct characters - this does a lot of redundant work:</p><ul><li><p>From index 0 you scan almost the whole string.</p></li><li><p>From index 1 you scan almost the whole string again.</p></li><li><p>And so on.</p></li></ul><p>That&#8217;s <code>O(n&#178;)</code> time.</p><p>In interviews, the naive approach is not &#8220;<em>wrong</em>&#8221;. It&#8217;s often a perfectly acceptable starting point. What matters is whether you recognize <em>why</em>it&#8217;s inefficient and can articulate the source of redundancy:</p><ul><li><p>&#8220;<em>We&#8217;re re-scanning the same characters many times</em>&#8221;.</p></li><li><p>&#8220;<em>We need a way to move the left boundary forward without re-checking everything inside</em>&#8221;.</p></li></ul><p>That statement is the bridge to the real solution.</p><h1>&#128161; The key insight</h1><p>The turning point is realizing that you don&#8217;t need to consider all substrings explicitly. You only need to maintain the best valid substring that ends at the current position.</p><p>Think of scanning the string left to right with a moving window <code>[left, right]</code> such that:</p><ul><li><p>The window contains no repeating characters.</p></li><li><p><code>right</code> moves forward one step at a time.</p></li><li><p>When the next character would violate the &#8220;<em>no repeats</em>&#8221; rule, you move <code>left</code> forward just enough to restore validity.</p></li></ul><p>The subtle part - and the part that separates &#8220;<em>good</em>&#8221; from &#8220;<em>strong</em>&#8221; - is how you move <code>left</code>.</p><p>A common but slightly clumsy version is to move <code>left</code> one step at a time, removing characters from a set until the duplicate is gone. That can still be <code>O(n)</code> overall if implemented carefully, but it&#8217;s harder to explain and easier to get wrong live.</p><p>The cleaner version uses <strong>last seen positions</strong>:</p><ul><li><p>Keep a map <code>lastSeen[c] = index</code> for each character <code>c</code>.</p></li><li><p>When you see character <code>c</code> at index <code>right</code>, and <code>c</code> was last seen at index <code>k</code>:</p><ul><li><p>If <code>k &lt; left</code>, it&#8217;s not a problem (the previous <code>c</code> is outside the window).</p></li><li><p>If <code>k &gt;= left</code>, it is a problem, and the new valid window must start at <code>k + 1</code>.</p></li></ul></li></ul><p>So you update: <code>left = max(left, lastSeen[c] + 1)</code>.</p><p>That one line is the heart of the algorithm. It encodes the idea: &#8220;<em>Jump the start forward past the previous occurrence, but never move it backward</em>&#8221;.</p><div><hr></div><h3>&#128161; Did this mental shift click for you?</h3><p>What was your &#8220;<em>aha</em>&#8221; moment while reading this?</p><p>&#128172; Leave a comment - I&#8217;d love to know how you think about Longest Substring Without Repeating Characters.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/thinking-clearly-in-interviews-longest/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/thinking-clearly-in-interviews-longest/comments"><span>Leave a comment</span></a></p><div><hr></div><h1>&#9881;&#65039; The final approach</h1><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5qYK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69503202-d601-4cdc-85ba-8203de14809b_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5qYK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69503202-d601-4cdc-85ba-8203de14809b_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!5qYK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69503202-d601-4cdc-85ba-8203de14809b_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!5qYK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69503202-d601-4cdc-85ba-8203de14809b_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!5qYK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69503202-d601-4cdc-85ba-8203de14809b_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5qYK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69503202-d601-4cdc-85ba-8203de14809b_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69503202-d601-4cdc-85ba-8203de14809b_1536x1024.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;:1297441,&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://iam.slys.dev/i/187834348?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69503202-d601-4cdc-85ba-8203de14809b_1536x1024.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_!5qYK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69503202-d601-4cdc-85ba-8203de14809b_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!5qYK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69503202-d601-4cdc-85ba-8203de14809b_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!5qYK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69503202-d601-4cdc-85ba-8203de14809b_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!5qYK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69503202-d601-4cdc-85ba-8203de14809b_1536x1024.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 role="img" 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><title></title><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>Narratively, here&#8217;s what you do:</p><p>You walk <code>right</code> from the start of the string to the end. You maintain:</p><ul><li><p><code>left</code>: the start index of the current window (the best candidate window ending at <code>right</code> that has no repeats).</p></li><li><p><code>lastSeen</code>: a mapping from character to the most recent index where it appeared.</p></li><li><p><code>best</code>: the maximum window length seen so far.</p></li></ul><p>At each character <code>c = s[right]</code>:</p><ol><li><p>If <code>c</code> has been seen before at index <code>k</code> and <code>k</code> is inside the current window (<code>k &gt;= left</code>), then the window is about to contain a duplicate. Slide <code>left</code> to <code>k + 1</code>.</p></li><li><p>Update <code>lastSeen[c] = right</code>.</p></li><li><p>Compute current window length as <code>right - left + 1</code>, update <code>best</code>.</p></li></ol><p>Correctness comes from maintaining an invariant:</p><ul><li><p>After processing each position <code>right</code>, the substring <code>s[left..right]</code> contains no repeated characters.</p></li><li><p>Among all valid substrings that end at <code>right</code>, <code>s[left..right]</code> is the longest (because <code>left</code> is as far left as possible while staying valid).</p></li></ul><p>Edge cases are naturally handled:</p><ul><li><p>Empty string: <code>best</code> stays 0.</p></li><li><p>All same character: window repeatedly collapses to length 1.</p></li><li><p>Repeats far apart: <code>left</code> jumps forward, never backward.</p></li></ul><p>This is exactly what you want in an interview solution: simple moving parts, one clear invariant, and no backtracking.</p><h1>&#9201;&#65039; Performance under interview constraints</h1><p>Time complexity is <code>O(n)</code> because each index is processed once, and <code>left</code> only moves forward. The map operations are expected <code>O(1)</code> on average.</p><p>Space complexity is <code>O(k)</code>, where <code>k</code> is the number of distinct characters you track. In the worst case it can be <code>O(n)</code> if the string has all unique characters, but practically it&#8217;s bounded by the character set size.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7CKu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3150f73-6cae-45b2-be9b-775ec951bf1c_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7CKu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3150f73-6cae-45b2-be9b-775ec951bf1c_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!7CKu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3150f73-6cae-45b2-be9b-775ec951bf1c_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!7CKu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3150f73-6cae-45b2-be9b-775ec951bf1c_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!7CKu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3150f73-6cae-45b2-be9b-775ec951bf1c_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7CKu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3150f73-6cae-45b2-be9b-775ec951bf1c_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f3150f73-6cae-45b2-be9b-775ec951bf1c_1536x1024.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;:1213304,&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://iam.slys.dev/i/187834348?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3150f73-6cae-45b2-be9b-775ec951bf1c_1536x1024.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_!7CKu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3150f73-6cae-45b2-be9b-775ec951bf1c_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!7CKu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3150f73-6cae-45b2-be9b-775ec951bf1c_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!7CKu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3150f73-6cae-45b2-be9b-775ec951bf1c_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!7CKu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3150f73-6cae-45b2-be9b-775ec951bf1c_1536x1024.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 role="img" 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><title></title><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>How do you justify this verbally?</p><ul><li><p>&#8220;<code>right</code><em> moves from 0 to n-1 exactly once</em>&#8221;.</p></li><li><p>&#8220;<code>left</code><em> only ever increases, at most n times</em>&#8221;.</p></li><li><p>&#8220;<em>Each character&#8217;s last-seen index is updated once per occurrence; we do </em><code>O(1)</code><em> expected work per character</em>&#8221;.</p></li></ul><p>If the interviewer presses on worst-case hash map behavior, a calm response is:</p><ul><li><p>&#8220;<em>In practice, standard library hash maps give good average behavior. If the character set is known to be small (like ASCII), we can replace the map with a fixed array to guarantee </em><code>O(1)</code><em> worst-case lookups</em>.&#8221;</p></li></ul><p>That&#8217;s the kind of trade-off talk that reads as engineering maturity.</p><div><hr></div><h3>&#9888;&#65039; Know someone preparing for interviews?</h3><p>Send this to them - it might save them from an avoidable mistake.</p><p>&#128257; Share this post with a friend grinding interview prep.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/thinking-clearly-in-interviews-longest?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/thinking-clearly-in-interviews-longest?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h1>&#128187; Implementation</h1><p>In interviews, implementation is secondary to clarity of thought - but the code still has to be correct, readable, and robust.</p><p>The most common implementation bugs here are:</p><ul><li><p>Updating <code>left</code> incorrectly (moving it backward, or not taking <code>max</code>).</p></li><li><p>Miscomputing window length (<code>right - left</code> instead of <code>+ 1</code>).</p></li><li><p>Confusing &#8220;<em>seen ever</em>&#8221; with &#8220;<em>seen in current window</em>&#8221;.</p></li></ul><p>So when you code, keep the structure aligned with the invariant:</p><ul><li><p>Read <code>right</code>, compute new <code>left</code> if needed, then update <code>lastSeen</code>, then update <code>best</code>.</p></li></ul><h2>&#128013; Python implementation</h2><p>Python is ideal for demonstrating the idea cleanly. Use a dictionary from character to last index.</p><pre><code>from typing import Dict

def length_of_longest_substring(s: str) -&gt; int:
    last_seen: Dict[str, int] = {}
    left = 0
    best = 0

    for right, ch in enumerate(s):
        if ch in last_seen and last_seen[ch] &gt;= left:
            # ch repeats inside the current window; jump left past the previous ch
            left = last_seen[ch] + 1

        last_seen[ch] = right
        best = max(best, right - left + 1)

    return best</code></pre><p>A good way to narrate this while typing:</p><ul><li><p>&#8220;<code>left</code><em> is the start of my current unique window</em>&#8221;.</p></li><li><p>&#8220;<code>last_seen</code><em> tells me where I last saw each character</em>&#8221;.</p></li><li><p>&#8220;<em>When I see a repeat inside the window, I jump </em><code>left</code><em> forward</em>&#8221;.</p></li><li><p>&#8220;<em>Then I compute the window length and update the best</em>&#8221;.</p></li></ul><p>If asked to return the substring itself, you can store best window boundaries (<code>best_left</code>, <code>best_right</code>) when updating <code>best</code>.</p><h2>&#129408; Rust implementation</h2><p>Rust adds one twist: <code>String</code> is UTF-8, and indexing by position is not allowed because indices are byte offsets, not character offsets. For this problem, we can iterate over <code>chars()</code> and treat &#8220;<em>length</em>&#8221; as the number of Unicode scalar values processed. That&#8217;s typically acceptable unless the interviewer explicitly wants byte-based behavior.</p><p>We&#8217;ll keep a <code>HashMap&lt;char, usize&gt;</code> storing the last seen <em>character index</em> (not byte index), maintained via <code>enumerate()</code> over <code>chars()</code>.</p><pre><code>use std::collections::HashMap;

pub fn length_of_longest_substring(s: &amp;str) -&gt; usize {
    let mut last_seen: HashMap&lt;char, usize&gt; = HashMap::new();
    let mut left: usize = 0;
    let mut best: usize = 0;

    for (right, ch) in s.chars().enumerate() {
        if let Some(&amp;prev) = last_seen.get(&amp;ch) {
            if prev &gt;= left {
                left = prev + 1;
            }
        }

        last_seen.insert(ch, right);
        let window_len = right - left + 1;
        if window_len &gt; best {
            best = window_len;
        }
    }

    best
}</code></pre><p>What to say out loud in a Rust interview:</p><ul><li><p>&#8220;<em>I&#8217;m iterating by </em><code>chars()</code><em>, so my indices are character positions</em>&#8221;.</p></li><li><p>&#8220;<em>Rust strings are UTF-8, so I avoid direct indexing</em>&#8221;.</p></li><li><p>&#8220;<em>Ownership is simple here: I borrow </em><code>&amp;str</code><em>, store </em><code>char</code><em> keys in the map, and store integer indices</em>&#8221;.</p></li></ul><p>If the interviewer wants maximum performance under an ASCII assumption, you can mention an optimization:</p><ul><li><p>Replace the <code>HashMap</code> with a <code>[i32; 256]</code> or <code>[usize; 128]</code> array (initialized to sentinel values), which avoids hashing entirely.</p></li></ul><h2>&#128995; Scala implementation</h2><p>In Scala, a straightforward approach uses a mutable map and integer indices. Scala&#8217;s <code>String</code> indexing uses UTF-16 code units, which is usually what interviewers assume when they say &#8220;<em>string</em>&#8221; in a typical backend context.</p><pre><code>import scala.collection.mutable

object LongestUniqueSubstring {
  def lengthOfLongestSubstring(s: String): Int = {
    val lastSeen = mutable.Map[Char, Int]()
    var left = 0
    var best = 0

    for (right &lt;- s.indices) {
      val ch = s.charAt(right)
      lastSeen.get(ch) match {
        case Some(prev) if prev &gt;= left =&gt;
          left = prev + 1
        case _ =&gt;
          // no action
      }

      lastSeen.update(ch, right)
      val windowLen = right - left + 1
      if (windowLen &gt; best) best = windowLen
    }

    best
  }
}</code></pre><p>Design choices worth briefly mentioning:</p><ul><li><p>Using a mutable map keeps the code close to the sliding window idea and avoids copying.</p></li><li><p>You could implement a purely functional version, but it tends to obscure the invariant under interview time constraints.</p></li><li><p>If you know the input is limited to ASCII, an array of size 128 or 256 is faster and simpler than hashing.</p></li></ul><h1>&#9888;&#65039; Common interview mistakes</h1><p>The most frequent mistake is forgetting that repeats only matter <strong>inside the current window</strong>, not &#8220;<em>ever</em>&#8221;. Candidates will sometimes do:</p><ul><li><p>&#8220;<em>If I&#8217;ve seen this character before, move left</em>&#8221;,</p></li></ul><p>&#8230;but without checking whether the previous occurrence is still inside the active window. That breaks cases like <code>"abba"</code>.</p><p>In <code>"abba"</code>, when you reach the last <code>'a'</code>, the previous <code>'a'</code> is at index 0, but the window might already start at index 2. If you move <code>left</code>back to 1, you violate the sliding window invariant. That&#8217;s why the condition <code>lastSeen[ch] &gt;= left</code> is non-negotiable.</p><p>Another classic mistake is updating <code>left</code> without taking <code>max</code> (in variants that compute <code>left = lastSeen[ch] + 1</code> unconditionally). If you don&#8217;t guard against moving <code>left</code> backward, you can &#8220;<em>re-include</em>&#8221; duplicates and produce inflated lengths.</p><p>Off-by-one errors show up constantly:</p><ul><li><p>Window length is <code>right - left + 1</code>.</p></li><li><p>If you set <code>left = prev</code> instead of <code>prev + 1</code>, you haven&#8217;t actually removed the duplicate.</p></li></ul><p>Finally, candidates sometimes choose a &#8220;<em>remove from set one-by-one</em>&#8221; approach and then get stuck in implementation details - forgetting to remove correctly, or accidentally making it quadratic by repeatedly re-scanning. It can be done correctly, but the last-seen-index jump is typically clearer and more robust under time pressure.</p><h1>&#128269; Edge cases interviewers love to ask about</h1><p>Interviewers often probe whether you truly understand the invariant by throwing targeted cases at you.</p><p>An empty string should return 0. This sounds trivial, but it tests whether your initialization is thoughtful or accidental. In many languages, it also tests whether you handle loops that never execute.</p><p>Strings with immediate repeats like <code>"aa"</code> or <code>"abba"</code> test the correctness of the <code>left</code> update logic. <code>"abba"</code> in particular is a favorite because it punishes &#8220;move left to lastSeen + 1 without checking window boundaries.&#8221;</p><p>Strings with spaces and punctuation (like <code>"a b!a"</code>) test whether you treat &#8220;<em>character</em>&#8221; broadly, not just letters. In most interpretations, every distinct character counts, including whitespace.</p><p>Very long strings test whether your method is truly linear. If you propose brute force, a good interviewer will ask, &#8220;<em>What happens at 100k characters</em>?&#8221; The best response isn&#8217;t panic - it&#8217;s a calm complexity argument and a shift to sliding window.</p><p>Sometimes you&#8217;ll get a follow-up: &#8220;<em>Can you return the substring, not just its length?</em>&#8221; If you wrote the window logic correctly, this is easy: track the best window boundaries whenever you update <code>best</code>. It&#8217;s also an opportunity to show you understand what your variables mean.</p><p>Another follow-up: &#8220;<em>What if the input is streaming and you can&#8217;t store the entire string?</em>&#8221; This pushes you to reason about what state you actually need (last seen positions and current index) and how you might handle eviction. It&#8217;s not always solvable perfectly without storing something, but the discussion itself reveals engineering judgment.</p><h1>&#127891; What this problem trains you to do</h1><p>This problem trains a specific kind of interview competence: maintaining a small, precise state that summarizes &#8220;<em>everything that matters so far</em>&#8221;.</p><p>You&#8217;re not memorizing a trick. You&#8217;re practicing how to:</p><ul><li><p>Define an invariant (&#8220;<em>this window is always valid</em>&#8221;).</p></li><li><p>Update state incrementally without recomputation.</p></li><li><p>Use auxiliary memory (a map) to convert &#8220;<em>searching backward</em>&#8221; into <code>O(1)</code> jumps.</p></li><li><p>Explain correctness as a story: &#8220;<em>When I see a repeat, the only way to restore validity is to move the left boundary past the previous occurrence</em>&#8221;.</p></li></ul><p>Once you internalize that, you start seeing the same shape in many other problems:</p><ul><li><p>Longest or shortest subarray satisfying a constraint.</p></li><li><p>Counting distinct elements in a window.</p></li><li><p>Minimum window containing a set of required characters.</p></li><li><p>Two-pointer techniques on arrays (sum constraints, unique constraints).</p></li><li><p>Streaming de-duplication with &#8220;<em>most recent occurrence</em>&#8221; metadata.</p></li></ul><p>More importantly, it teaches you how to stay calm when requirements are deceptively small. The interviewer isn&#8217;t asking for heroics. They&#8217;re asking whether you can be precise.</p><h1>&#127793; Closing thoughts</h1><p>The core skill here is resisting the urge to &#8220;<em>restart</em>&#8221; whenever you hit a problem. In live coding, restarts show up as nested loops, rescans, and tangled conditionals - symptoms of not having a stable invariant.</p><p>A sliding window solution is what it looks like when you trust your state: you keep a clear boundary around what&#8217;s currently valid, and when reality violates your expectation, you adjust the boundary instead of throwing away your work.</p><p>If you practice explaining this problem out loud - what <code>left</code> means, why <code>left</code> never moves backward, and how <code>lastSeen</code> prevents rescanning - you&#8217;ll notice a shift. You stop sounding like someone searching for a solution and start sounding like someone executing a plan.</p><div><hr></div><h3>&#129504; If you want to build real interview intuition&#8230;</h3><p>I write deep, calm breakdowns of classic problems - without tricks or memorization.</p><p>&#128236; Subscribe to get the next one directly.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/subscribe?"><span>Subscribe now</span></a></p>]]></content:encoded></item><item><title><![CDATA[Why is my LoadBalancer still <pending>?]]></title><description><![CDATA[How Cilium's LB IPAM and L2 Announcements turn a pending LoadBalancer Service into a reachable VIP on your LAN.]]></description><link>https://iam.slys.dev/p/why-is-my-loadbalancer-still-pending</link><guid isPermaLink="false">https://iam.slys.dev/p/why-is-my-loadbalancer-still-pending</guid><dc:creator><![CDATA[Jakub Slys 🤖]]></dc:creator><pubDate>Mon, 23 Mar 2026 21:28:39 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!5sE8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ae29c03-ff4a-4536-af69-ae53fec9c271_1920x1080.heic" 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_!5sE8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ae29c03-ff4a-4536-af69-ae53fec9c271_1920x1080.heic" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5sE8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ae29c03-ff4a-4536-af69-ae53fec9c271_1920x1080.heic 424w, https://substackcdn.com/image/fetch/$s_!5sE8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ae29c03-ff4a-4536-af69-ae53fec9c271_1920x1080.heic 848w, https://substackcdn.com/image/fetch/$s_!5sE8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ae29c03-ff4a-4536-af69-ae53fec9c271_1920x1080.heic 1272w, https://substackcdn.com/image/fetch/$s_!5sE8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ae29c03-ff4a-4536-af69-ae53fec9c271_1920x1080.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5sE8!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ae29c03-ff4a-4536-af69-ae53fec9c271_1920x1080.heic" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9ae29c03-ff4a-4536-af69-ae53fec9c271_1920x1080.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:106876,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/190302892?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ae29c03-ff4a-4536-af69-ae53fec9c271_1920x1080.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!5sE8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ae29c03-ff4a-4536-af69-ae53fec9c271_1920x1080.heic 424w, https://substackcdn.com/image/fetch/$s_!5sE8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ae29c03-ff4a-4536-af69-ae53fec9c271_1920x1080.heic 848w, https://substackcdn.com/image/fetch/$s_!5sE8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ae29c03-ff4a-4536-af69-ae53fec9c271_1920x1080.heic 1272w, https://substackcdn.com/image/fetch/$s_!5sE8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ae29c03-ff4a-4536-af69-ae53fec9c271_1920x1080.heic 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 role="img" 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><title></title><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>&#9888;&#65039; <strong>Before we dive in &#8212; highly worth your attention</strong></p><div class="embedded-publication-wrap" data-attrs="{&quot;id&quot;:3343898,&quot;name&quot;:&quot;Unpromptable.&quot;,&quot;logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!102n!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd215e8b4-a9c5-49a0-a2ef-c911251bfff0_500x500.png&quot;,&quot;base_url&quot;:&quot;https://unpromptable.substack.com&quot;,&quot;hero_text&quot;:&quot;Helping founders, creatives, and professionals become irreplaceable in the Age of AI || Subscribe: forever free 2x deep dives, community events, and free Active Prompt Vault (+ more AI &amp; marketing tools).&quot;,&quot;author_name&quot;:&quot;James Presbitero&quot;,&quot;show_subscribe&quot;:true,&quot;logo_bg_color&quot;:&quot;#ecfdf5&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="EmbeddedPublicationToDOMWithSubscribe"><div class="embedded-publication show-subscribe"><a class="embedded-publication-link-part" native="true" href="https://unpromptable.substack.com?utm_source=substack&amp;utm_campaign=publication_embed&amp;utm_medium=web"><img class="embedded-publication-logo" src="https://substackcdn.com/image/fetch/$s_!102n!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd215e8b4-a9c5-49a0-a2ef-c911251bfff0_500x500.png" width="56" height="56" style="background-color: rgb(236, 253, 245);"><span class="embedded-publication-name">Unpromptable.</span><div class="embedded-publication-hero-text">Helping founders, creatives, and professionals become irreplaceable in the Age of AI || Subscribe: forever free 2x deep dives, community events, and free Active Prompt Vault (+ more AI &amp; marketing tools).</div><div class="embedded-publication-author-name">By James Presbitero</div></a><form class="embedded-publication-subscribe" method="GET" action="https://unpromptable.substack.com/subscribe?"><input type="hidden" name="source" value="publication-embed"><input type="hidden" name="autoSubmit" value="true"><input type="email" class="email-input" name="email" placeholder="Type your email..."><input type="submit" class="button primary" value="Subscribe"></form></div></div><p><span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;James Presbitero&quot;,&quot;id&quot;:112381382,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!Zwf9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0763a29d-cc76-47d0-b18a-5567aee11ade_572x572.png&quot;,&quot;uuid&quot;:&quot;83071405-edc2-4c60-b486-63c9500decf4&quot;}" data-component-name="MentionToDOM"></span> writes about <strong>startups</strong>, <strong>leadership</strong>, and the realities of <strong>building companies</strong> from the inside. His posts combine <strong>founder experience with practical reflections</strong> on decision-making, growth, and navigating uncertainty - the kind of thinking that&#8217;s useful if you&#8217;re actually building something.</p><div><hr></div><p>You deploy the standard Kubernetes pattern: an app Deployment, plus a Service of <code>type: LoadBalancer</code>. You run <code>kubectl get svc</code> and expect an external IP you can curl from your laptop. Instead:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">$ kubectl get svc -n demo
NAME          TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
demo-web      LoadBalancer   10.96.120.200    &lt;pending&gt;     80:31234/TCP   20s</code></pre></div><p>On cloud-managed clusters, this works because a cloud controller provisions a managed load balancer and writes the resulting IP into the Service's <code>.status.loadBalancer</code> field. Kubernetes delegates this provisioning to an external implementation - it doesn't provide one itself.</p><p>On bare metal, that cloud integration doesn't exist. Nothing chooses an IP from your LAN, and nothing announces that IP on your local network so traffic can find it. That's why the Service stays pending: <strong>no component has taken responsibility for the Service's external presence.</strong></p><p>This article builds that missing responsibility using Cilium's documented bare-metal path: <strong>LB IPAM<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></strong> allocates an IP for your <code>LoadBalancer</code> Service, and <strong>L2 Announcements</strong><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a> makes that IP reachable on your local network by responding to ARP and NDP queries. These are distinct problems with distinct mechanisms - understanding the separation is the whole game.</p><h1>What Cilium is (and what it isn't)</h1><p>Kubernetes networking has two separate layers that are easy to conflate.</p><p><strong>Pod networking</strong>: when a pod starts, something must create its network interface, assign an IP, and wire up routes. Kubernetes delegates this to the Container Network Interface (CNI)<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a> model - a runtime calls a CNI plugin to configure container networking. The CNI boundary is "<em>getting pods on the network</em>", nothing more.</p><p><strong>Service exposure</strong>: kube-proxy (or a replacement) takes a virtual ClusterIP/port and forwards traffic to backend pods. <code>LoadBalancer</code> Services extend this with an external IP - but Kubernetes explicitly leaves the external load balancer implementation to outside components. On bare metal, that means the cluster can be internally healthy while having no way to make a Service real on your LAN.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!crti!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f714d91-05a1-4b9e-bb00-835c56546fa7_1600x900.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!crti!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f714d91-05a1-4b9e-bb00-835c56546fa7_1600x900.png 424w, https://substackcdn.com/image/fetch/$s_!crti!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f714d91-05a1-4b9e-bb00-835c56546fa7_1600x900.png 848w, https://substackcdn.com/image/fetch/$s_!crti!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f714d91-05a1-4b9e-bb00-835c56546fa7_1600x900.png 1272w, https://substackcdn.com/image/fetch/$s_!crti!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f714d91-05a1-4b9e-bb00-835c56546fa7_1600x900.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!crti!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f714d91-05a1-4b9e-bb00-835c56546fa7_1600x900.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5f714d91-05a1-4b9e-bb00-835c56546fa7_1600x900.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:118103,&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://iam.slys.dev/i/190302892?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f714d91-05a1-4b9e-bb00-835c56546fa7_1600x900.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!crti!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f714d91-05a1-4b9e-bb00-835c56546fa7_1600x900.png 424w, https://substackcdn.com/image/fetch/$s_!crti!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f714d91-05a1-4b9e-bb00-835c56546fa7_1600x900.png 848w, https://substackcdn.com/image/fetch/$s_!crti!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f714d91-05a1-4b9e-bb00-835c56546fa7_1600x900.png 1272w, https://substackcdn.com/image/fetch/$s_!crti!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f714d91-05a1-4b9e-bb00-835c56546fa7_1600x900.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 role="img" 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><title></title><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>Cilium spans both layers. As a CNI plugin it handles pod networking. It also implements service load balancing in-kernel using its own datapath, and can run in <strong>kube-proxy replacement mode</strong> - a prerequisite for L2 Announcements. For bare metal specifically, Cilium provides two building blocks:</p><ul><li><p><strong>LB IPAM</strong>: allocates IPs from a configured pool and assigns them to <code>LoadBalancer</code> Services. It is always enabled but dormant until you create at least one pool.</p></li><li><p><strong>L2 Announcements</strong>: responds to ARP (IPv4) and NDP (IPv6) queries for Service VIPs, making them reachable on the local network. Only one node responds for a given Service IP at a time, then load-balances to pods.</p></li></ul><blockquote><p>IP allocation (LB IPAM) and IP reachability on the LAN (L2 Announcements) are separate steps. Debug them separately.</p></blockquote><h1>Installing and Validating Cilium</h1><h2>Installing the Cilium CLI</h2><p>The Cilium CLI<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a> is your workstation-side tool: you run it from a machine with kubeconfig access. Its job is installing Cilium, inspecting a Cilium installation, and enabling or disabling features like ClusterMesh or Hubble. It is not "<em>Cilium running</em>" - it's a client. The actual datapath work happens inside the cluster via the agent DaemonSet and operator Deployment.</p><p>The documented install method downloads the latest stable CLI from the CLI repository's <code>stable.txt</code>:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
CLI_ARCH=amd64
if [ "$(uname -m)" = "aarch64" ]; then CLI_ARCH=arm64; fi

curl -L --fail --remote-name-all \
  https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}

sha256sum --check cilium-linux-${CLI_ARCH}.tar.gz.sha256sum
sudo tar xzvfC cilium-linux-${CLI_ARCH}.tar.gz /usr/local/bin
rm cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}</code></pre></div><p>Verify it's present and connects to your environment:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">which cilium
cilium version</code></pre></div><p>This distinction between CLI and cluster components matters later: when you edit the <code>cilium-config</code> ConfigMap, you'll need to restart pods to pick up the change. The CLI doesn't do that automatically.</p><h2>Installing Cilium into the cluster</h2><p>From a "<em>bring your own CNI</em>" bare-metal cluster, the CLI-driven install is the shortest supported path:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">cilium install</code></pre></div><p>The installer attempts to pick appropriate defaults for your distribution and stores state as CRDs. If you need strict reproducibility, pin a version with <code>--version 1.19.1</code>. For this walkthrough we rely on validation rather than pinned versions.</p><p>After installation, wait for readiness:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">cilium status --wait
   /&#175;&#175;\
/&#175;&#175;\__/&#175;&#175;\    Cilium:         OK
\__/&#175;&#175;\__/    Operator:       OK
/&#175;&#175;\__/&#175;&#175;\    Hubble:         disabled
\__/&#175;&#175;\__/    ClusterMesh:    disabled
   \__/

DaemonSet         cilium             Desired: 2, Ready: 2/2, Available: 2/2
Deployment        cilium-operator    Desired: 2, Ready: 2/2, Available: 2/2
Containers:       cilium-operator    Running: 2
                  cilium             Running: 2
Image versions    cilium             quay.io/cilium/cilium:v1.9.5: 2
                  cilium-operator    quay.io/cilium/operator-generic:v1.9.5: 2</code></pre></div><p>This reports both the DaemonSet (agent) and Deployment (operator) reaching desired/ready counts. You can confirm with Kubernetes primitives in parallel:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">kubectl -n kube-system get pods -l k8s-app=cilium
kubectl -n kube-system get deploy cilium-operator</code></pre></div><p>One prerequisite to carry forward: L2 Announcements requires <strong>kube-proxy replacement mode</strong><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a> to be enabled. At this stage you don't need to configure anything - just keep it in mind before expecting LoadBalancer VIPs to work externally.</p><h1>Reproducing the pending LoadBalancer and fixing IP allocation</h1><h2>Creating a LoadBalancer service (it will be Pending)</h2><p>To understand what we're fixing, create the failure deliberately. Deploy a minimal HTTP server and expose it as a <code>LoadBalancer</code><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-6" href="#footnote-6" target="_self">6</a> Service:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">kubectl create namespace demo
kubectl -n demo create deployment demo-web --image=nginx --port=80
kubectl -n demo expose deployment demo-web --type=LoadBalancer --port=80</code></pre></div><p>Check the Service:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">kubectl -n demo get svc</code></pre></div><p>On a bare-metal cluster with no external load balancer integration, <code>EXTERNAL-IP</code> shows <code>&lt;pending&gt;</code>. Kubernetes treats <code>type: LoadBalancer</code> as an abstraction that requires an external implementation to allocate an external IP and write it into <code>.status.loadBalancer</code>.</p><p>Cilium's LB IPAM documentation is explicit about what <code>&lt;pending&gt;</code> means: no LB IPs have been assigned. It expresses this state through Service status conditions - for example <code>io.cilium/lb-ipam-request-satisfied</code> with reason <code>no_pool</code> when no matching pool exists.</p><p>The important checkpoint here: <strong>nothing is wrong with your Deployment</strong>. Pods may be healthy, ClusterIP traffic may work, NodePort may work. What's absent:</p><ul><li><p>No IP allocation policy for LoadBalancer Services (no pool exists or matches)</p></li><li><p>No L2 reachability mechanism (L2 Announcements is not enabled; nothing answers ARP for the VIP)</p></li></ul><p>Fix these in order: allocate an IP first, then make it reachable.</p><div><hr></div><p><strong>Which tools are </strong><em><strong>you</strong></em><strong> using?</strong></p><p>Have you tried Nginx, Envoy, or maybe you&#8217;re wrestling with AWS&#8217;s ELB quirks? I&#8217;d love to hear your thoughts, questions, or stories from the trenches.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/why-is-my-loadbalancer-still-pending/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/why-is-my-loadbalancer-still-pending/comments"><span>Leave a comment</span></a></p><div><hr></div><h2>Configuring LoadBalancer IP pool (LB-IPAM)</h2><p>LB IPAM answers: "<em>Which IP addresses are allowed to be assigned to LoadBalancer Services in this cluster?</em>" It is designed for environments where cloud facilities are absent, and is always enabled but dormant until the first pool exists.</p><p>The CRD for pools is <code>CiliumLoadBalancerIPPool</code> (<code>apiVersion: cilium.io/v2</code>). The <code>spec.blocks</code> field defines allocatable IP space, either as CIDRs or as explicit start/stop ranges.</p><p>A practical bare-metal pattern: carve out a dedicated sub-range in your LAN that your DHCP server doesn't touch, reachable within the same L2 domain as your nodes. The numbers depend on your LAN; below is an example using a small "<em>VIP slice</em>" inside <code>192.168.111.0/24</code>:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;yaml&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-yaml">apiVersion: "cilium.io/v2"
kind: CiliumLoadBalancerIPPool
metadata:
  name: lan-vips
spec:
  blocks:
    - start: "192.168.111.200"
      stop:  "192.168.111.250"</code></pre></div><p>Apply it and verify capacity:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">kubectl apply -f lan-vips.yaml
kubectl get ippools
kubectl describe ippools/lan-vips</code></pre></div><p><code>kubectl get ippools</code> shows <code>DISABLED</code>, <code>CONFLICTING</code>, and <code>IPS AVAILABLE</code>. If you accidentally create overlapping pools, LB IPAM marks the later pool as conflicting and stops allocating from it.</p><p>Once a matching pool exists, LB IPAM assigns an IP to the pending Service. Check:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">kubectl -n demo get svc
kubectl -n demo get svc/demo-web -o jsonpath='{.status.conditions}'
echo</code></pre></div><p>At this point <strong>allocation is solved</strong>. Reachability is not. Your network has no reason to send traffic for that VIP to any node - nothing is answering ARP for it yet.</p><p><strong>Trade-off worth naming here</strong>: L2 Announcements is the simpler bare-metal path - no BGP router required, no additional configuration on your upstream network. The cost is scope: it only works within a single L2 domain. If your nodes span multiple VLANs or subnets, L2 Announcements won't bridge them. In that case, Cilium's BGP control plane<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-7" href="#footnote-7" target="_self">7</a> is the right approach instead. Everything that follows assumes a flat L2 network.</p><h1>Enabling L2 Announcements for bare metal</h1><h3>Enabling L2 Announcements (ConfigMap method)</h3><p>L2 Announcements makes Service VIPs reachable on the local network by responding to ARP (IPv4) or NDP (IPv6) queries. Because these VIPs aren't literally configured as addresses on any NIC, one elected node replies with its MAC and acts as the north/south entry point for that Service.</p><p>Two prerequisites:</p><ul><li><p><strong>kube-proxy replacement must be enabled</strong></p></li><li><p>Network interfaces you intend to announce on must be part of the devices Cilium uses for service handling (relevant if you've set device filtering explicitly)</p></li></ul><p>Enable L2 Announcements in the <code>cilium-config</code> ConfigMap:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">kubectl edit configmap -n kube-system cilium-config</code></pre></div><p>Add (or confirm) under <code>data:</code>:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;yaml&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-yaml">enable-l2-announcements: "true"</code></pre></div><p>Changing configuration via ConfigMap requires a pod restart to take effect. Complete the RBAC step below first, then restart both together.</p><p><strong>RBAC</strong>: L2 Announcements uses Kubernetes leader election based on Lease<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-8" href="#footnote-8" target="_self">8</a> objects (<code>coordination.k8s.io</code> API group). Without the right permissions, the agent cannot create or update the Lease objects it needs, and the feature fails even with the ConfigMap key set. Cilium's own troubleshooting documentation calls this out directly: if you see "<em>forbidden</em>" errors against <code>leases.coordination.k8s.io</code>, you must update the <code>cilium</code> ClusterRole.</p><p>Edit the ClusterRole:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">kubectl edit clusterrole cilium</code></pre></div><p>Add this rule block under <code>rules:</code> if it's not already present:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;yaml&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-yaml">- apiGroups:
  - coordination.k8s.io
  resources:
  - leases
  verbs:
  - create
  - get
  - update
  - list
  - delete</code></pre></div><p>This RBAC change is not optional for manual enablement. Lease-based leader election is fundamental to how L2 Announcements works - each selected Service maps to a Lease, and the Lease holder is the sole responder to ARP/NDP for that Service's VIP.</p><h2>Restarting Cilium and verifying L2 is active</h2><p>Restart the DaemonSet to pick up both changes:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">kubectl -n kube-system rollout restart ds/cilium
kubectl -n kube-system rollout status ds/cilium</code></pre></div><p>Verify in three layers.</p><p><strong>Internal configuration</strong> - confirm the feature flags are active inside a running agent pod:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">kubectl -n kube-system exec ds/cilium -- cilium-dbg config --all | grep EnableL2Announcements
kubectl -n kube-system exec ds/cilium -- cilium-dbg config --all | grep KubeProxyReplacement</code></pre></div><p><strong>Overall health</strong>:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">cilium status --wait
    /&#175;&#175;\
 /&#175;&#175;\__/&#175;&#175;\    Cilium:         OK
 \__/&#175;&#175;\__/    Operator:       OK
 /&#175;&#175;\__/&#175;&#175;\    Hubble:         OK
 \__/&#175;&#175;\__/    ClusterMesh:    disabled
    \__/

Deployment        cilium-operator    Desired: 2, Ready: 2/2, Available: 2/2
DaemonSet         cilium             Desired: 2, Ready: 2/2, Available: 2/2
Containers:       cilium-operator    Running: 2
                  cilium             Running: 2
Cluster Pods:     5/5 managed by Cilium</code></pre></div><p><strong>Service state</strong> - confirm IP allocation is still satisfied after the restart:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">kubectl -n demo get svc demo-web
kubectl -n demo get svc demo-web -o jsonpath='{.status.conditions}'
echo</code></pre></div><p>The agent now participates in Service-specific leader election and can respond to ARP/NDP for selected VIPs. But nothing is announced yet: <strong>L2 Announcements won't announce any VIP until you define at least one </strong><code>CiliumL2AnnouncementPolicy</code>.</p><h2>Creating a CiliumL2AnnouncementPolicy</h2><p>A <code>CiliumL2AnnouncementPolicy</code> is the selection logic that turns "<em>L2 Announcements is enabled</em>" into "<em>this particular Service VIP is announced on this particular interface by one eligible node</em>".</p><p>Current stable API:</p><ul><li><p><code>apiVersion: cilium.io/v2alpha1</code></p></li><li><p><code>kind: CiliumL2AnnouncementPolicy</code></p></li></ul><p>A minimal policy for bare metal:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;yaml&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-yaml">apiVersion: "cilium.io/v2alpha1"
kind: CiliumL2AnnouncementPolicy
metadata:
  name: demo-l2
spec:
  serviceSelector:
    matchLabels:
      app: demo-web
  nodeSelector:
    matchExpressions:
      - key: node-role.kubernetes.io/control-plane
        operator: DoesNotExist
  interfaces:
    - ^eth[0-9]+
  loadBalancerIPs: true</code></pre></div><p>A few things about this policy worth understanding:</p><ul><li><p><code>serviceSelector</code> uses a standard label selector. Cilium also supports special keys like <code>io.kubernetes.service.namespace</code> and <code>io.kubernetes.service.name</code> to match by namespace or name without adding labels to Services.</p></li><li><p><code>nodeSelector</code> here excludes control-plane nodes - a reasonable default for bare-metal clusters where you don't want ingress traffic landing on the control plane.</p></li><li><p><code>interfaces</code> takes Go regex patterns. <code>^eth[0-9]+</code> matches <code>eth0</code>, <code>eth1</code>, and so on. Interface patterns only take effect on interfaces Cilium already considers for service handling - verify with <code>cilium-dbg shell -- db/show devices</code>.</p></li><li><p><code>loadBalancerIPs: true</code> is required. Both <code>externalIPs</code> and <code>loadBalancerIPs</code> default to false; at least one must be explicitly enabled or no VIPs are announced.</p></li></ul><p>Apply the policy and label the Service so it matches:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">kubectl -n demo label svc demo-web app=demo-web --overwrite
kubectl apply -f demo-l2-policy.yaml</code></pre></div><p>One matching detail that often goes unnoticed: a Service must have <code>loadBalancerClass</code> unset or set to <code>io.cilium/l2-announcer</code> to be eligible for announcement. If <code>loadBalancerClass</code> is set to something else, the policy won't select it even if every other selector matches.</p><p>Once the policy exists and matches, Cilium creates a per-Service Lease and begins announcing the VIP from the current lease-holder node.</p><h1>Using specific VIPs and understanding the traffic path</h1><h2>Assigning a specific IP to a Service</h2><p>Once LB IPAM has a pool, you can either accept any free VIP or request a specific one. Use a specific IP when the address becomes part of an external contract - a DNS A record, a NAT rule on your router, an upstream allowlist - because those external references need to stay stable across Service restarts.</p><p>The Cilium-supported annotation for this is <code>lbipam.cilium.io/ips</code>:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">kubectl -n demo annotate svc demo-web lbipam.cilium.io/ips="192.168.111.11" --overwrite</code></pre></div><p>Or in manifest form:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;yaml&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-yaml">apiVersion: v1
kind: Service
metadata:
  name: demo-web
  namespace: demo
  annotations:
    "lbipam.cilium.io/ips": "192.168.111.11"
spec:
  type: LoadBalancer
  selector:
    app: demo-web
  ports:
    - port: 80
      targetPort: 80</code></pre></div><p>The legacy <code>.spec.loadBalancerIP</code> field was deprecated in Kubernetes v1.24 and its behavior varies across implementations. Prefer the annotation.</p><p>LB IPAM validates two things: the requested IP must fall within an existing pool, and the pool's <code>serviceSelector</code> must match the Service. A request that doesn't satisfy both stays unallocated. Also avoid requesting the first or last IP in a pool - many IPv4 networks treat those as network and broadcast addresses, and Cilium's docs explicitly warn against them.</p><div><hr></div><p><strong>Know someone who&#8217;s just getting into backend development or cloud architecture</strong></p><p>If this post helped you, pass it along - help them level up too. &#128071;</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/leaderboard?&amp;utm_source=post&quot;,&quot;text&quot;:&quot;Refer a friend&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/leaderboard?&amp;utm_source=post"><span>Refer a friend</span></a></p><div><hr></div><h3>End-to-end traffic flow</h3><p>Once LB IPAM assigns a VIP and L2 Announcements is active, the path from the outside becomes deterministic. Using the common home-lab pattern of public DNS &#8594; router NAT &#8594; LAN VIP.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Vvj1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99bd5ac0-ed3f-459b-8b27-1fad00903d6a_1600x900.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Vvj1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99bd5ac0-ed3f-459b-8b27-1fad00903d6a_1600x900.png 424w, https://substackcdn.com/image/fetch/$s_!Vvj1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99bd5ac0-ed3f-459b-8b27-1fad00903d6a_1600x900.png 848w, https://substackcdn.com/image/fetch/$s_!Vvj1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99bd5ac0-ed3f-459b-8b27-1fad00903d6a_1600x900.png 1272w, https://substackcdn.com/image/fetch/$s_!Vvj1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99bd5ac0-ed3f-459b-8b27-1fad00903d6a_1600x900.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Vvj1!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99bd5ac0-ed3f-459b-8b27-1fad00903d6a_1600x900.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/99bd5ac0-ed3f-459b-8b27-1fad00903d6a_1600x900.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:74512,&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://iam.slys.dev/i/190302892?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99bd5ac0-ed3f-459b-8b27-1fad00903d6a_1600x900.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Vvj1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99bd5ac0-ed3f-459b-8b27-1fad00903d6a_1600x900.png 424w, https://substackcdn.com/image/fetch/$s_!Vvj1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99bd5ac0-ed3f-459b-8b27-1fad00903d6a_1600x900.png 848w, https://substackcdn.com/image/fetch/$s_!Vvj1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99bd5ac0-ed3f-459b-8b27-1fad00903d6a_1600x900.png 1272w, https://substackcdn.com/image/fetch/$s_!Vvj1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99bd5ac0-ed3f-459b-8b27-1fad00903d6a_1600x900.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 role="img" 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><title></title><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 few steps worth understanding explicitly.</p><p><strong>The VIP is an ordinary LAN IP.</strong> Your router forwards to it the same way it would forward to any host on the LAN - not to a cloud load balancer appliance, not through any tunnel. The VIP address is real to the LAN; it's only "<em>virtual</em>" in the sense that no NIC has it configured as a static address.</p><p><strong>ARP provides the binding.</strong> To forward a packet to the VIP, the router must resolve which MAC address owns it. Cilium L2 Announcements responds to those ARP queries (or NDP for IPv6) on behalf of the VIP, returning the MAC of the current leader node.</p><p><strong>One node holds the Lease.</strong> ARP caches keep one MAC per IP - multiple responders would cause flapping. Cilium enforces single ownership through Kubernetes Lease-based leader election: one node holds the Lease per Service and is the sole ARP responder for that VIP.</p><p><strong>Failover is real but not instant.</strong> If the leader stops renewing the Lease, other eligible nodes race to take over. The new leader sends gratuitous ARP to update neighbor caches. Some clients ignore gratuitous ARP for security reasons, which can extend the failover window beyond the nominal lease timers. This is worth understanding before putting L2 Announcements in front of latency-sensitive workloads.</p><h1>Troubleshooting</h1><h2>Debugging layer by layer</h2><p>When a <code>LoadBalancer</code> Service on bare metal fails, debug in the same order traffic must succeed: Service state &#8594; IP allocation &#8594; L2 selection &#8594; ARP visibility &#8594; Lease ownership.</p><p><strong>Service status (Kubernetes view)</strong></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">kubectl -n demo get svc demo-web
kubectl -n demo describe svc demo-web
kubectl -n demo get svc/demo-web -o jsonpath='{.status.conditions}'
echo</code></pre></div><p><code>&lt;pending&gt;</code> means no LB IPs have been assigned. The condition <code>io.cilium/lb-ipam-request-satisfied</code> with reason <code>no_pool</code> means no enabled pool matched the Service.</p><p><strong>IP allocation (LB IPAM view)</strong></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">kubectl get ippools
kubectl describe ippools/lan-vips</code></pre></div><p>Check <code>DISABLED</code> and <code>CONFLICTING</code>. Overlapping pools cause a conflict and block allocation from the conflicting pool. Also confirm your Service labels match any pool <code>serviceSelector</code> you configured.</p><p><strong>L2 policy match (Cilium L2 view)</strong></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">kubectl get CiliumL2AnnouncementPolicy
kubectl describe CiliumL2AnnouncementPolicy demo-l2</code></pre></div><p>Invalid policies surface errors as status conditions (for example <code>io.cilium/bad-service-selector</code>). Also check <code>loadBalancerClass</code> on the Service - L2 Announcements selects Services with <code>loadBalancerClass</code> unset or set to <code>io.cilium/l2-announcer</code>.</p><p><strong>ARP visibility (network view)</strong></p><p>From a host on the same LAN as your nodes:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">arp -a | grep 192.168.111.11</code></pre></div><p>If ARP never resolves, the VIP isn't being announced. The problem is in Cilium configuration, not in pod health.</p><p><strong>Lease objects (leader election view)</strong></p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">kubectl -n kube-system get lease | grep cilium-l2announce</code></pre></div><p>If no Leases exist, either the policy doesn't match or the agent can't create them. If agent logs mention "<em>forbidden</em>" access to <code>leases.coordination.k8s.io</code>, the RBAC step was missed.</p><p>For deeper inspection from inside an agent pod:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;bash&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-bash">kubectl -n kube-system exec ds/cilium -- cilium-dbg shell -- db/show l2-announce
kubectl -n kube-system exec ds/cilium -- cilium-dbg shell -- db/show devices</code></pre></div><p>These show which IPs are announced on which interfaces, and whether the interface is in Cilium's device list.</p><div><hr></div><p><strong>&#128161; Want more like this delivered to your inbox?</strong></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h1>Closing thoughts</h1><p>Two problems, two mechanisms.</p><p><strong>LB IPAM</strong> answers "<em>which IP?</em>" - it gives your <code>LoadBalancer</code> Service an address from a pool you define. Without it, the Service stays <code>&lt;pending&gt;</code> indefinitely.</p><p><strong>L2 Announcements</strong> answers "<em>which MAC?</em>" - it makes that IP visible on your LAN by responding to ARP and NDP on behalf of the VIP. Without it, the IP exists in Kubernetes but is unreachable from the network.</p><p>Things to keep close:</p><ul><li><p>LB IPAM is always running but dormant - it activates the moment you create the first pool.</p></li><li><p>L2 Announcements requires kube-proxy replacement mode and Lease RBAC. Both must be in place before the feature does anything.</p></li><li><p>L2 scope is one L2 domain. If your nodes span VLANs or subnets, use Cilium's BGP control plane instead.</p></li><li><p>One node holds the Lease per Service. Failover exists but isn't instant - gratuitous ARP helps, but some clients ignore it.</p></li><li><p>Debug in order: Service conditions &#8594; pool status &#8594; policy match &#8594; ARP table &#8594; Lease objects.</p></li><li><p>Request specific IPs with the <code>lbipam.cilium.io/ips</code> annotation, not the deprecated <code>.spec.loadBalancerIP</code> field.</p></li><li><p>Interface patterns in <code>CiliumL2AnnouncementPolicy</code> are Go regex and must match interfaces in Cilium's device list - confirm with <code>db/show devices</code>.</p></li></ul><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p><a href="https://docs.cilium.io/en/stable/network/lb-ipam/">Cilium: LoadBalancer IP Address Management (LB IPAM)</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p><a href="https://docs.cilium.io/en/stable/network/l2-announcements/">Cilium: L2 Announcements / L2 Aware LB (Beta)</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p><a href="https://github.com/containernetworking/cni">CNI - the Container Network Interface</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-4" href="#footnote-anchor-4" class="footnote-number" contenteditable="false" target="_self">4</a><div class="footnote-content"><p><a href="https://github.com/cilium/cilium-cli">Cilium CLI</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-5" href="#footnote-anchor-5" class="footnote-number" contenteditable="false" target="_self">5</a><div class="footnote-content"><p><a href="https://docs.cilium.io/en/stable/network/kubernetes/kubeproxy-free/">Kubernetes Without kube-proxy</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-6" href="#footnote-anchor-6" class="footnote-number" contenteditable="false" target="_self">6</a><div class="footnote-content"><p><a href="https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer">Kubernetes / Service / type: LoadBalancer</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-7" href="#footnote-anchor-7" class="footnote-number" contenteditable="false" target="_self">7</a><div class="footnote-content"><p><a href="https://docs.cilium.io/en/stable/network/bgp-control-plane/bgp-control-plane/">Cilium BGP Control Plane</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-8" href="#footnote-anchor-8" class="footnote-number" contenteditable="false" target="_self">8</a><div class="footnote-content"><p><a href="https://docs.cilium.io/en/stable/network/l2-announcements/#leases">L2 Announcements / L2 Aware LB (Beta) / Leases</a></p></div></div>]]></content:encoded></item><item><title><![CDATA[Logistic Regression — when machines learn to say yes or no]]></title><description><![CDATA[Machine learning fundamentals]]></description><link>https://iam.slys.dev/p/logistic-regression-when-machines</link><guid isPermaLink="false">https://iam.slys.dev/p/logistic-regression-when-machines</guid><dc:creator><![CDATA[Jakub Slys 🤖]]></dc:creator><pubDate>Mon, 16 Mar 2026 21:38:18 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!5HaR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3e578d4-d44c-4e77-b3c0-212b9dc9352e_1920x1080.heic" 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_!5HaR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3e578d4-d44c-4e77-b3c0-212b9dc9352e_1920x1080.heic" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5HaR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3e578d4-d44c-4e77-b3c0-212b9dc9352e_1920x1080.heic 424w, https://substackcdn.com/image/fetch/$s_!5HaR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3e578d4-d44c-4e77-b3c0-212b9dc9352e_1920x1080.heic 848w, https://substackcdn.com/image/fetch/$s_!5HaR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3e578d4-d44c-4e77-b3c0-212b9dc9352e_1920x1080.heic 1272w, https://substackcdn.com/image/fetch/$s_!5HaR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3e578d4-d44c-4e77-b3c0-212b9dc9352e_1920x1080.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5HaR!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3e578d4-d44c-4e77-b3c0-212b9dc9352e_1920x1080.heic" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e3e578d4-d44c-4e77-b3c0-212b9dc9352e_1920x1080.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:86623,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/187836360?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3e578d4-d44c-4e77-b3c0-212b9dc9352e_1920x1080.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!5HaR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3e578d4-d44c-4e77-b3c0-212b9dc9352e_1920x1080.heic 424w, https://substackcdn.com/image/fetch/$s_!5HaR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3e578d4-d44c-4e77-b3c0-212b9dc9352e_1920x1080.heic 848w, https://substackcdn.com/image/fetch/$s_!5HaR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3e578d4-d44c-4e77-b3c0-212b9dc9352e_1920x1080.heic 1272w, https://substackcdn.com/image/fetch/$s_!5HaR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3e578d4-d44c-4e77-b3c0-212b9dc9352e_1920x1080.heic 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 role="img" 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><title></title><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>&#9888;&#65039; Before we begin &#8212; a practical AI newsletter worth following</strong></p><div class="embedded-publication-wrap" data-attrs="{&quot;id&quot;:6335167,&quot;name&quot;:&quot;GenAI Unplugged&quot;,&quot;logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!bW7t!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59c51495-c9ae-4442-8cab-2bf1341fee46_1024x1024.png&quot;,&quot;base_url&quot;:&quot;https://genaiunplugged.substack.com&quot;,&quot;hero_text&quot;:&quot;Simple AI automation systems for solopreneurs who are done doing everything by hand.&quot;,&quot;author_name&quot;:&quot;Dheeraj Sharma&quot;,&quot;show_subscribe&quot;:true,&quot;logo_bg_color&quot;:&quot;#ffffff&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="EmbeddedPublicationToDOMWithSubscribe"><div class="embedded-publication show-subscribe"><a class="embedded-publication-link-part" native="true" href="https://genaiunplugged.substack.com?utm_source=substack&amp;utm_campaign=publication_embed&amp;utm_medium=web"><img class="embedded-publication-logo" src="https://substackcdn.com/image/fetch/$s_!bW7t!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F59c51495-c9ae-4442-8cab-2bf1341fee46_1024x1024.png" width="56" height="56" style="background-color: rgb(255, 255, 255);"><span class="embedded-publication-name">GenAI Unplugged</span><div class="embedded-publication-hero-text">Simple AI automation systems for solopreneurs who are done doing everything by hand.</div><div class="embedded-publication-author-name">By Dheeraj Sharma</div></a><form class="embedded-publication-subscribe" method="GET" action="https://genaiunplugged.substack.com/subscribe?"><input type="hidden" name="source" value="publication-embed"><input type="hidden" name="autoSubmit" value="true"><input type="email" class="email-input" name="email" placeholder="Type your email..."><input type="submit" class="button primary" value="Subscribe"></form></div></div><p><em><strong>GenAI Unplugged</strong></em> by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Dheeraj Sharma&quot;,&quot;id&quot;:394741552,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!mIDa!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3edd1f31-6669-445d-8285-dd01139794ab_1080x1080.png&quot;,&quot;uuid&quot;:&quot;8ff1a2bf-9ee3-4113-9992-7f99041a8556&quot;}" data-component-name="MentionToDOM"></span> focuses on building simple AI automation systems for solopreneurs. Instead of abstract AI discussions, you&#8217;ll find step-by-step guides for creating agents, automating workflows, and turning repetitive work into systems that actually save time.</p><div><hr></div><p>Binary classification sounds crisp: <em>yes</em> or <em>no</em>, <em>spam</em> or <em>not spam</em>, <em>churn</em> or <em>stay</em>. But most real decisions don&#8217;t feel crisp at all. They feel like standing in fog with a flashlight: you can see <em>some</em> evidence, but not enough to feel certain.</p><p>Think about a simple question a product team might ask: &#8220;<em>Will this package arrive late?</em>&#8221; There&#8217;s a tracking history, a carrier, a destination, weather, time of year, warehouse load. You don&#8217;t look at those signals and instantly &#8220;know&#8221; the answer. What you actually form is a belief - an internal probability. <em>Probably late.</em> <em>Maybe on time.</em> And only after that belief forms do you decide what to do: proactively message the customer, offer a discount, or do nothing.</p><p>Logistic regression is the machine learning version of that habit. It does not begin by trying to shout &#8220;<em>YES</em>&#8221; or &#8220;<em>NO</em>&#8221;. It begins by learning how to <em>weigh evidence</em> and turn that evidence into a <em>probability</em>. The &#8220;<em>classification</em>&#8221; part - the conversion from probability to a label - comes later, and (crucially) it is not a law of nature. It&#8217;s a choice you make based on costs, risk tolerance, and what kind of mistakes your system can live with.</p><p>This post is a slow walk through that mental model. We&#8217;ll build logistic regression from the inside out: an evidence score, a squashing function, a probability, and then an optional decision rule. We&#8217;ll derive the loss function step by step (no &#8220;<em>it can be shown</em>&#8221;), and we&#8217;ll do small numeric examples you can reproduce with a calculator. If you&#8217;ve ever felt that logistic regression was &#8220;<em>just a formula</em>&#8221;, the goal here is to make it feel like a clear, reasonable machine for turning messy signals into honest odds.</p><h1>A yes-or-no question rarely feels like yes-or-no</h1><p>Imagine you run a subscription app and you&#8217;re looking at a particular user. The question on your dashboard reads: &#8220;<em>Will this customer churn in the next 30 days?</em>&#8221; That is technically a binary question. Either they will, or they won&#8217;t.</p><p>But your <em>experience</em> of the question isn&#8217;t binary. You don&#8217;t think in labels first. You think in likelihoods: <em>They haven&#8217;t logged in for two weeks&#8230; that&#8217;s bad. But they just upgraded&#8230; that&#8217;s good. They contacted support twice&#8230; unclear.</em> Your brain starts doing an informal accounting of evidence, and the output is rarely a hard label. It&#8217;s something like: &#8220;<em>I&#8217;m worried. Maybe 70%</em>&#8221;.</p><p>That &#8220;<em>odds-first</em>&#8221; habit is not a weakness; it&#8217;s often the most rational way to behave under uncertainty. If an action is expensive (a retention phone call), you might require high confidence. If an action is cheap (an automated helpful email), you might act on weaker suspicion.</p><p>Logistic regression fits neatly into this worldview. It aims to learn a mapping from features (signals) to a probability like 0.72, not directly to a label. It learns <em>how strongly each signal should influence the belief</em>, using past data as feedback.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!DiIT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d2de666-9edc-4991-aff7-40d65c4c0d45_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!DiIT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d2de666-9edc-4991-aff7-40d65c4c0d45_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!DiIT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d2de666-9edc-4991-aff7-40d65c4c0d45_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!DiIT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d2de666-9edc-4991-aff7-40d65c4c0d45_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!DiIT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d2de666-9edc-4991-aff7-40d65c4c0d45_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!DiIT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d2de666-9edc-4991-aff7-40d65c4c0d45_1536x1024.png" width="727.9962768554688" height="485.49751705127755" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2d2de666-9edc-4991-aff7-40d65c4c0d45_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:727.9962768554688,&quot;bytes&quot;:3295212,&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://iam.slys.dev/i/187836360?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d2de666-9edc-4991-aff7-40d65c4c0d45_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!DiIT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d2de666-9edc-4991-aff7-40d65c4c0d45_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!DiIT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d2de666-9edc-4991-aff7-40d65c4c0d45_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!DiIT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d2de666-9edc-4991-aff7-40d65c4c0d45_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!DiIT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d2de666-9edc-4991-aff7-40d65c4c0d45_1536x1024.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 role="img" 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><title></title><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 subtle point that matters later: the model&#8217;s probability is not a statement about a single individual&#8217;s soul. It&#8217;s a statement about <em>frequency in similar cases</em>. If the model outputs 0.7 on many users, you want roughly 70% of those users (in that slice of feature space) to actually churn. That&#8217;s the core: treat binary outcomes as probabilistic events with learnable structure.</p><div><hr></div><p>&#128270; <em><strong>Ever wondered how machines actually decide &#8220;yes&#8221; or &#8220;no&#8221;?</strong></em></p><p>If you enjoy breaking down machine learning ideas into clear intuition instead of heavy math, you&#8217;ll probably like the rest of this series. <strong>Subscribe &#128071;</strong></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h1>Why probabilities are often more useful than labels</h1><p>If you force every prediction into a hard 0 or 1, you throw away information that could have driven better decisions.</p><p>Consider two churn predictions:</p><ul><li><p>User <code>A: (p = 0.51)</code></p></li><li><p>User <code>B: (p = 0.99)</code></p></li></ul><p>If you use a default threshold of <code>0.5</code>, both become &#8220;<em>yes: will churn</em>&#8221;. But treating these users identically is usually irrational. User A is barely over the line - almost a coin flip. User B is practically screaming.</p><p>In real systems, this difference affects:</p><ul><li><p><strong>Resource allocation.</strong> A retention team might have time to call only the riskiest users. You want to sort by probability, not by label.</p></li><li><p><strong>Human review.</strong> Borderline cases are perfect for a queue, where a person can decide with extra context.</p></li><li><p><strong>User experience.</strong> You might show a gentle in-app nudge at <code>0.6</code>, but a stronger offer at <code>0.95</code>.</p></li><li><p><strong>Cost-sensitive decisions.</strong> If false positives are expensive, you may require a higher probability before acting.</p></li></ul><p>Probabilities also let you talk about performance in a richer way. Accuracy collapses everything into &#8220;<em>right or wrong</em>&#8221;, but probabilities support calibration curves, expected cost calculations, and ranking metrics. A model that says <code>0.6</code> for everything might get some labels right, but it&#8217;s not <em>useful</em> in the same way a well-shaped probability model is.</p><p>So the goal is not merely to &#8220;<em>classify</em>&#8221;. The goal is to produce a probability that is as <em>honest</em> as possible - meaning: aligned with reality across many examples. Logistic regression is one of the simplest models that tries to do exactly that, and its simplicity is part of why it&#8217;s still worth learning deeply.</p><h1>The model&#8217;s inner voice: &#8220;<em>How much evidence points to yes?</em>&#8221;</h1><p>Before we name anything, let&#8217;s build the mental picture.</p><p>Logistic regression creates a single number - a kind of internal &#8220;<em>evidence score</em>&#8221;. Each feature contributes a push:</p><ul><li><p>Some features push the score upward (more evidence for &#8220;<em>yes</em>&#8221;).</p></li><li><p>Others push it downward (more evidence for &#8220;<em>n</em>o&#8221;).</p></li><li><p>The pushes add together.</p></li></ul><p>This is very close to how you might make a decision with a checklist. &#8220;<em>Late delivery risk</em>&#8221; might increase if it&#8217;s winter, if the destination is far, if the carrier is overloaded. Those are pushes. You add them up into an overall sense of risk.</p><p>Mathematically, this &#8220;<em>weighted checklist</em>&#8221; is a linear combination. Suppose your features are:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;x_1, x_2, \\dots, x_d&quot;,&quot;id&quot;:&quot;BYDLRTRECE&quot;}" data-component-name="LatexBlockToDOM"></div><p>The model learns weights:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;w_1, w_2, \\dots, w_d&quot;,&quot;id&quot;:&quot;QKTSGNNXVI&quot;}" data-component-name="LatexBlockToDOM"></div><p></p><p>And it also learns a baseline offset (often called an intercept):</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;b&quot;,&quot;id&quot;:&quot;RRRWYALYJV&quot;}" data-component-name="LatexBlockToDOM"></div><p>The evidence score is:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;z = b + \\sum_i w_i x_i&quot;,&quot;id&quot;:&quot;IFLZRVJWHE&quot;}" data-component-name="LatexBlockToDOM"></div><p>That&#8217;s the whole inner voice: <em>a sum of nudges</em>. If <code>(w&#7522;)</code> is positive, higher <code>(x&#7522;)</code> pushes toward &#8220;<em>yes</em>&#8221;. If <code>(w&#7522;)</code> is negative, higher <code>(x&#7522;)</code> pushes toward &#8220;<em>no</em>&#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_!x9Cj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F106f1770-8966-4a6c-bad6-f0c4e6114b60_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!x9Cj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F106f1770-8966-4a6c-bad6-f0c4e6114b60_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!x9Cj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F106f1770-8966-4a6c-bad6-f0c4e6114b60_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!x9Cj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F106f1770-8966-4a6c-bad6-f0c4e6114b60_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!x9Cj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F106f1770-8966-4a6c-bad6-f0c4e6114b60_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!x9Cj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F106f1770-8966-4a6c-bad6-f0c4e6114b60_1536x1024.png" width="727.9962768554688" height="485.49751705127755" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/106f1770-8966-4a6c-bad6-f0c4e6114b60_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:727.9962768554688,&quot;bytes&quot;:2991566,&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://iam.slys.dev/i/187836360?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F106f1770-8966-4a6c-bad6-f0c4e6114b60_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!x9Cj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F106f1770-8966-4a6c-bad6-f0c4e6114b60_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!x9Cj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F106f1770-8966-4a6c-bad6-f0c4e6114b60_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!x9Cj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F106f1770-8966-4a6c-bad6-f0c4e6114b60_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!x9Cj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F106f1770-8966-4a6c-bad6-f0c4e6114b60_1536x1024.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 role="img" 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><title></title><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><h2>Worked example: computing an evidence score</h2><p><strong>Problem.</strong> Compute the evidence score <code>(z)</code>.</p><p><strong>Given.</strong></p><ul><li><p><code>(b = -1.2)</code></p></li><li><p><code>(w&#8321; = 0.8), (x&#8321; = 2.0)</code></p></li><li><p><code>(w&#8322; = -0.5), (x&#8322; = 1.0)</code></p></li><li><p><code>(w&#8323; = 0.3), (x&#8323; = 4.0)</code></p></li></ul><p><strong>Step 1: compute each push.</strong></p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;w_1x_1 = 0.8 \\cdot 2.0 = 1.6&quot;,&quot;id&quot;:&quot;NGTNOYKSXZ&quot;}" data-component-name="LatexBlockToDOM"></div><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;w_2x_2 = -0.5 \\cdot 1.0 = -0.5&quot;,&quot;id&quot;:&quot;YOZUDMYAKV&quot;}" data-component-name="LatexBlockToDOM"></div><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;w_3x_3 = 0.3 \\cdot 4.0 = 1.2&quot;,&quot;id&quot;:&quot;SOIJHJBRIT&quot;}" data-component-name="LatexBlockToDOM"></div><p><strong>Step 2: add them with the intercept.</strong></p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;z = b + 1.6 - 0.5 + 1.2&quot;,&quot;id&quot;:&quot;OBDMHIUNAL&quot;}" data-component-name="LatexBlockToDOM"></div><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;z = -1.2 + 2.3&quot;,&quot;id&quot;:&quot;MEUEUGAXRH&quot;}" data-component-name="LatexBlockToDOM"></div><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;z = 1.1&quot;,&quot;id&quot;:&quot;QUNGRWEQAC&quot;}" data-component-name="LatexBlockToDOM"></div><p><strong>Meaning.</strong> The model&#8217;s internal evidence is positive <code>((z = 1.1))</code>, so it is leaning toward &#8220;<em>yes</em>&#8221;. But we still don&#8217;t have a probability - yet.</p><h1>The squashing step that turns evidence into a probability</h1><p>An evidence score like <code>(z)</code> can be any real number: <code>(-10)</code>, <code>(1.1)</code>, <code>(200)</code>. But a probability must live between <code>0</code> and <code>1</code>. So we need a function that converts an unbounded score into a bounded probability.</p><p>Even before we name the function, we can describe what we want:</p><ul><li><p>Very negative evidence should map to a probability near <code>0</code>.</p></li><li><p>Very positive evidence should map to a probability near <code>1</code>.</p></li><li><p>Evidence near <code>0</code> should map to something like &#8220;<em>uncertain</em>&#8221;, around <code>0.5</code>.</p></li><li><p>The mapping should be smooth, not a hard step, because small evidence changes shouldn&#8217;t cause discontinuous probability jumps.</p></li></ul><p>The classic choice is the <strong>sigmoid</strong> (also called the logistic function). It&#8217;s defined as:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\sigma(z) = \\frac{1}{1 + e^{-z}}&quot;,&quot;id&quot;:&quot;ZSTJXHRNZE&quot;}" data-component-name="LatexBlockToDOM"></div><p>And logistic regression uses:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;p = \\sigma(z)&quot;,&quot;id&quot;:&quot;NMXQSSTWJV&quot;}" data-component-name="LatexBlockToDOM"></div><p>where <code>(p)</code> is the predicted probability of the positive class (&#8220;<em>yes</em>&#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_!77WJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef3728f9-2f66-414f-a1ab-eb51b9bd7fc8_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!77WJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef3728f9-2f66-414f-a1ab-eb51b9bd7fc8_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!77WJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef3728f9-2f66-414f-a1ab-eb51b9bd7fc8_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!77WJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef3728f9-2f66-414f-a1ab-eb51b9bd7fc8_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!77WJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef3728f9-2f66-414f-a1ab-eb51b9bd7fc8_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!77WJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef3728f9-2f66-414f-a1ab-eb51b9bd7fc8_1536x1024.png" width="724.3749389648438" height="483.0824627299885" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ef3728f9-2f66-414f-a1ab-eb51b9bd7fc8_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:724.3749389648438,&quot;bytes&quot;:3273376,&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://iam.slys.dev/i/187836360?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef3728f9-2f66-414f-a1ab-eb51b9bd7fc8_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!77WJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef3728f9-2f66-414f-a1ab-eb51b9bd7fc8_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!77WJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef3728f9-2f66-414f-a1ab-eb51b9bd7fc8_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!77WJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef3728f9-2f66-414f-a1ab-eb51b9bd7fc8_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!77WJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef3728f9-2f66-414f-a1ab-eb51b9bd7fc8_1536x1024.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 role="img" 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><title></title><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>Why this shape? One intuitive way to see it is to look at extremes:</p><p>If <code>(z)</code> is very large and positive, then <code>(-z)</code> is very negative, so <code>(e&#8315;&#7611;)</code> is near <code>0</code>. Then:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;p \\approx \\frac{1}{1 + 0} = 1&quot;,&quot;id&quot;:&quot;JJEZCALECO&quot;}" data-component-name="LatexBlockToDOM"></div><p>If <code>(z)</code> is very large and negative, then <code>(-z)</code> is very positive, so <code>(e&#8315;&#7611;)</code> is huge. Then the denominator is huge, and <code>(p)</code> is near <code>0</code>.</p><p>At <code>(z = 0)</code>:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;p = \\frac{1}{1 + e^0}&quot;,&quot;id&quot;:&quot;YQJGPYYRAF&quot;}" data-component-name="LatexBlockToDOM"></div><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;p = \\frac{1}{2}&quot;,&quot;id&quot;:&quot;YWAQFPOBNH&quot;}" data-component-name="LatexBlockToDOM"></div><p>So zero evidence corresponds to <code>50/50</code> odds. And the curve is S-shaped: slow at the ends, fast in the middle. That &#8220;<em>fast in the middle</em>&#8221; turns out to be where most of the learning action lives.</p><div><hr></div><p><strong>&#128161; </strong><em><strong>Did this visualization make logistic regression finally click?</strong></em></p><p>Sometimes a single diagram explains what pages of equations cannot.</p><p>&#128172; <strong>Leave a comment</strong> - I&#8217;m curious what part made the idea clearer for you.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/logistic-regression-when-machines/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/logistic-regression-when-machines/comments"><span>Leave a comment</span></a></p><div><hr></div><h2>Worked example: from evidence to probability</h2><p><strong>Problem.</strong> Convert <code>(z = 1.1)</code> into a probability.</p><p><strong>Given.</strong> <code>(z = 1.1)</code></p><p><strong>Step 1: compute </strong><code>(e&#8315;&#7611;)</code><strong>.</strong></p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;e^{-1.1} \\approx 0.3329&quot;,&quot;id&quot;:&quot;YUJUFSVRXN&quot;}" data-component-name="LatexBlockToDOM"></div><p><strong>Step 2: compute the denominator.</strong></p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;1 + e^{-1.1} \\approx 1.3329&quot;,&quot;id&quot;:&quot;PMVFPKINPU&quot;}" data-component-name="LatexBlockToDOM"></div><p><strong>Step 3: invert.</strong></p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;p = \\frac{1}{1.3329} \\approx 0.7502&quot;,&quot;id&quot;:&quot;UPIYVUGXCP&quot;}" data-component-name="LatexBlockToDOM"></div><p><strong>Meaning.</strong> Evidence score <code>(1.1)</code> corresponds to about a <code>75%</code> predicted chance of &#8220;<em>yes</em>&#8221;. Notice how that feels: a positive lean, not absolute certainty.</p><h1>Why the middle matters: uncertainty lives near the boundary</h1><p>The sigmoid&#8217;s most important region is not near <code>0</code> or near <code>1</code>. It&#8217;s the middle.</p><p>When <code>(z)</code> is very large (say <code>(z = 8)</code>), the sigmoid is already extremely close to <code>1</code>. Changing <code>(z)</code> a little doesn&#8217;t change the probability much:</p><ul><li><p><code>(z = 8 &#8658; p &#8776; 0.9997)</code></p></li><li><p><code>(z = 7 &#8658; p &#8776; 0.9991)</code></p></li></ul><p>Those are different numbers, but they are operationally similar: <em>high confidence &#8220;yes&#8221;.</em></p><p>In contrast, near <code>(z = 0)</code>, small changes move the probability a lot:</p><ul><li><p><code>(z = 0 &#8658; p = 0.5)</code></p></li><li><p><code>(z = 0.4 &#8658; p &#8776; 0.598)</code></p></li><li><p><code>(z = -0.4 &#8658; p &#8776; 0.401)</code></p></li></ul><p>This region corresponds to borderline cases - users who might churn or might not, emails that look a bit spammy but not definitely spam, transactions that are suspicious but plausibly legitimate.</p><p>Two things make the middle region special:</p><ol><li><p><strong>During training</strong>, these examples carry a lot of information. If the model is uncertain but wrong, it needs to adjust weights so similar cases move the correct direction. If the model is already extremely confident and correct, there&#8217;s not much to learn from that point.</p></li><li><p><strong>During deployment</strong>, these examples are the risky ones. A slight shift in the real world (seasonality, new user behavior, a policy change) can push many borderline cases across your chosen threshold, causing visible behavior changes.</p></li></ol><p>If you remember only one operational lesson: pay attention to the probability mass near your decision boundary. That&#8217;s where your metrics will be sensitive, where calibration matters, and where product decisions about thresholds will show up as real outcomes.</p><h1>From probability to decision: the threshold is not part of the truth</h1><p>Logistic regression outputs a probability <code>(p)</code>. That&#8217;s the model&#8217;s belief.</p><p>A <strong>decision rule</strong> is something you add on top:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\hat{y} = \n\\begin{cases} \n1 &amp; \\text{if } p \\ge t \\\\ \n0 &amp; \\text{if } p < t \n\\end{cases}&quot;,&quot;id&quot;:&quot;ZEDESGZTUP&quot;}" data-component-name="LatexBlockToDOM"></div><p>Here <code>(t)</code> is the threshold you choose.</p><p>It&#8217;s tempting to treat <code>(t = 0.5)</code> as &#8220;<em>the default</em>&#8221;, almost like physics. But it&#8217;s not physics. It&#8217;s values.</p><p>To see why, imagine two scenarios:</p><p><strong>Medical screening.</strong> A test flags &#8220;<em>possible disease</em>&#8221;. Missing a true case (false negative) might be very costly. You might set <code>(t)</code> low, perhaps <code>0.2</code>, accepting more false alarms in exchange for catching more true positives. The follow-up test might be cheap and safe, so false positives are tolerable.</p><p><strong>Account bans for fraud.</strong> Now a false positive is a serious accusation that harms a user. You might set <code>(t)</code> high, maybe <code>0.95</code>, accepting that you will miss some fraud in exchange for avoiding wrongful bans.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!APZ4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa486e6e5-237b-4fbe-913a-ef1624517028_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!APZ4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa486e6e5-237b-4fbe-913a-ef1624517028_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!APZ4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa486e6e5-237b-4fbe-913a-ef1624517028_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!APZ4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa486e6e5-237b-4fbe-913a-ef1624517028_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!APZ4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa486e6e5-237b-4fbe-913a-ef1624517028_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!APZ4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa486e6e5-237b-4fbe-913a-ef1624517028_1536x1024.png" width="727.9962768554688" height="485.49751705127755" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a486e6e5-237b-4fbe-913a-ef1624517028_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:727.9962768554688,&quot;bytes&quot;:3039199,&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://iam.slys.dev/i/187836360?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa486e6e5-237b-4fbe-913a-ef1624517028_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!APZ4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa486e6e5-237b-4fbe-913a-ef1624517028_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!APZ4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa486e6e5-237b-4fbe-913a-ef1624517028_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!APZ4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa486e6e5-237b-4fbe-913a-ef1624517028_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!APZ4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa486e6e5-237b-4fbe-913a-ef1624517028_1536x1024.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 role="img" 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><title></title><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>In both cases, the same predicted probability can lead to a different action. That&#8217;s not inconsistency; it&#8217;s a separation of responsibilities:</p><ul><li><p>The model estimates probabilities as honestly as it can.</p></li><li><p>The system chooses actions based on costs and risk tolerance.</p></li></ul><h2>Worked example: choosing a threshold by expected cost</h2><p><strong>Problem.</strong> Pick the cheaper action using expected cost.</p><p><strong>Given.</strong></p><ul><li><p>Model outputs <code>(p = 0.30)</code> for &#8220;<em>fraud</em>&#8221;.</p></li><li><p>Cost of blocking a legitimate user: <code>(C</code><sub>FP</sub><code> = 50)</code></p></li><li><p>Cost of letting fraud through: <code>(C</code><sub>FN</sub><code> = 10)</code></p></li></ul><p>If we <strong>block</strong>, we pay <code>(50)</code> only if it&#8217;s not fraud, which happens with probability <code>(1 - p)</code>.</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;E[\\text{cost}|\\text{block}] = (1-p)\\cdot 50&quot;,&quot;id&quot;:&quot;OORDACBVSZ&quot;}" data-component-name="LatexBlockToDOM"></div><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;= 0.70 \\cdot 50 = 35&quot;,&quot;id&quot;:&quot;XEAHWETYNY&quot;}" data-component-name="LatexBlockToDOM"></div><p>If we <strong>allow</strong>, we pay <code>(10)</code> only if it <em>is</em> fraud, which happens with probability (p).</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;E[\\text{cost}|\\text{allow}] = p\\cdot 10&quot;,&quot;id&quot;:&quot;GWOPZZKRLP&quot;}" data-component-name="LatexBlockToDOM"></div><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;= 0.30 \\cdot 10 = 3&quot;,&quot;id&quot;:&quot;XFUVLCFLMJ&quot;}" data-component-name="LatexBlockToDOM"></div><p><strong>Decision.</strong> Allow is much cheaper in expectation <code>(3 vs 35)</code>. Even though <code>30%</code> fraud risk sounds scary, the action costs dominate the choice. This is the kind of reasoning probabilities enable - and hard labels destroy.</p><h1>A grounded example: churn prediction as a weighted checklist</h1><p>Let&#8217;s make this concrete with a small churn story. Suppose we run a subscription app and define &#8220;<em>churn</em>&#8221; as canceling within 30 days. We build features for each user:</p><ul><li><p><code>(x&#8321;):</code> days since last login</p></li><li><p><code>(x&#8322;):</code> number of support tickets in last 30 days</p></li><li><p><code>(x&#8323;):</code> discount usage (0 or 1)</p></li><li><p><code>(x&#8324;):</code> plan type (0 for annual, 1 for monthly)</p></li></ul><p>We train logistic regression and get weights (these are fictional but plausible):</p><ul><li><p><code>(b = -2.0)</code></p></li><li><p><code>(w&#8321; = 0.12)</code></p></li><li><p><code>(w&#8322; = 0.40)</code></p></li><li><p><code>(w</code><sub>3</sub><code> = 0.90)</code></p></li><li><p><code>(w</code><sub>4</sub><code> = 0.70)</code></p></li></ul><p>Interpretation: more days since login increases churn risk; more support tickets increases churn risk; using discounts is a risk signal (maybe bargain-seekers churn); monthly plans churn more than annual.</p><p>Now compare two users.</p><h2>User A (mild risk)</h2><ul><li><p>days since login: <code>(x&#8321; = 8)</code></p></li><li><p>support tickets: <code>(x&#8322; = 1)</code></p></li><li><p>used discount: <code>(x</code><sub>3</sub><code> = 0)</code></p></li><li><p>monthly plan: <code>(x</code><sub>4</sub><code> = 1)</code></p></li></ul><p>Evidence score:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;z = -2.0 \\cdot 0.12 \\cdot 8 \\cdot 0.40\\cdot 1 \\cdot 0.90\\cdot 0 \\cdot 0.70\\cdot 1&quot;,&quot;id&quot;:&quot;MGZCXMWRJE&quot;}" data-component-name="LatexBlockToDOM"></div><p>Compute pushes:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;0.12\\cdot 8 = 0.96;\n 0.40\\cdot 1 = 0.40; \n0.90\\cdot 0 = 0;\n0.70\\cdot 1 = 0.70;&quot;,&quot;id&quot;:&quot;ALSLURIFWS&quot;}" data-component-name="LatexBlockToDOM"></div><p>Sum:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;z = -2.0 + 0.96 + 0.40 + 0 + 0.70 = 0.06&quot;,&quot;id&quot;:&quot;CKOHTDQNGW&quot;}" data-component-name="LatexBlockToDOM"></div><p>Probability:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;p = \\sigma(0.06) \\approx 0.515&quot;,&quot;id&quot;:&quot;LQIOQZPQUZ&quot;}" data-component-name="LatexBlockToDOM"></div><p>User A is barely above <code>50/50</code>: &#8220;<em>keep an eye on them</em>&#8221;.</p><h2>User B (high risk)</h2><ul><li><p>days since login: <code>(x&#8321; = 20)</code></p></li><li><p>support tickets: <code>(x&#8322; = 3)</code></p></li><li><p>used discount: <code>(x</code><sub>3</sub><code> = 1)</code></p></li><li><p>monthly plan: <code>(x</code><sub>4</sub><code> = 1)</code></p></li></ul><p>Evidence:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;z = -2.0 \\cdot 0.12\\cdot 20 \\cdot 0.40\\cdot 3 \\cdot 0.90\\cdot 1 \\cdot 0.70\\cdot 1&quot;,&quot;id&quot;:&quot;COZNLNLGZI&quot;}" data-component-name="LatexBlockToDOM"></div><p>Compute pushes:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;0.12\\cdot 20 = 2.40; 0.40\\cdot 3 = 1.20&quot;,&quot;id&quot;:&quot;VDRVWANXIG&quot;}" data-component-name="LatexBlockToDOM"></div><p>Sum:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;z = -2.0 + 2.40 + 1.20 + 0.90 + 0.70  = 3.20&quot;,&quot;id&quot;:&quot;RABDKOUKYC&quot;}" data-component-name="LatexBlockToDOM"></div><p>Probability:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;p = \\sigma(3.20) \\approx 0.961&quot;,&quot;id&quot;:&quot;LMATSKPQFW&quot;}" data-component-name="LatexBlockToDOM"></div><p>Now we have two &#8220;<em>likely churn</em>&#8221; users, but one is <code>~0.52</code> and the other is <code>~0.96</code>. In a real retention workflow, User A might get a gentle reminder email. User B might justify a retention call or a targeted offer. The power here is not the label; it&#8217;s the ranked, calibrated belief.</p><h1>What training is actually doing: adjusting how much each signal counts</h1><p>So far we&#8217;ve treated the weights as magic numbers we somehow obtained. Training is the process of choosing those weights so that the predicted probabilities match reality well across many examples.</p><p>Let&#8217;s formalize one data point. For user <code>(n)</code>:</p><ul><li><p>features: <code>(x&#8317;&#8319;&#8318;)</code></p></li><li><p>label: <code>(y&#8317;&#8319;&#8318; &#8712; 0, 1)</code></p></li></ul><ul><li><p>predicted probability: <code>[ p&#8317;&#8319;&#8318; = &#963;(z&#8317;&#8319;&#8318;) ]</code></p></li><li><p>evidence score: <code>[ z&#8317;&#8319;&#8318; = b + w&#7488;x&#8317;&#8319;&#8318; ]</code></p></li></ul><p>Now: how should a model be rewarded or punished? Intuitively:</p><ul><li><p>If the true label is <code>1</code> and the model says <code>(p = 0.99)</code>, that&#8217;s great.</p></li><li><p>If the true label is <code>1</code> and the model says <code>(p = 0.51)</code>, that&#8217;s only mildly good.</p></li><li><p>If the true label is <code>1</code> and the model says <code>(p = 0.01)</code>, that&#8217;s disastrously overconfident and should hurt a lot.</p></li></ul><p>This &#8220;<em>confidently wrong should hurt more</em>&#8221; idea leads to <strong>log loss</strong> (also called cross-entropy for binary classification). Here&#8217;s the clean derivation from probability, not from tradition.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!y-ZE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff98970c5-8a65-4871-b278-5c3ca990a4f5_960x540.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!y-ZE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff98970c5-8a65-4871-b278-5c3ca990a4f5_960x540.gif 424w, https://substackcdn.com/image/fetch/$s_!y-ZE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff98970c5-8a65-4871-b278-5c3ca990a4f5_960x540.gif 848w, https://substackcdn.com/image/fetch/$s_!y-ZE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff98970c5-8a65-4871-b278-5c3ca990a4f5_960x540.gif 1272w, https://substackcdn.com/image/fetch/$s_!y-ZE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff98970c5-8a65-4871-b278-5c3ca990a4f5_960x540.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!y-ZE!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff98970c5-8a65-4871-b278-5c3ca990a4f5_960x540.gif" width="1200" height="675" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f98970c5-8a65-4871-b278-5c3ca990a4f5_960x540.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:540,&quot;width&quot;:960,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:314274,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/187836360?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff98970c5-8a65-4871-b278-5c3ca990a4f5_960x540.gif&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!y-ZE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff98970c5-8a65-4871-b278-5c3ca990a4f5_960x540.gif 424w, https://substackcdn.com/image/fetch/$s_!y-ZE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff98970c5-8a65-4871-b278-5c3ca990a4f5_960x540.gif 848w, https://substackcdn.com/image/fetch/$s_!y-ZE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff98970c5-8a65-4871-b278-5c3ca990a4f5_960x540.gif 1272w, https://substackcdn.com/image/fetch/$s_!y-ZE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff98970c5-8a65-4871-b278-5c3ca990a4f5_960x540.gif 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 role="img" 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><title></title><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><h2>Step-by-step derivation from a Bernoulli likelihood</h2><p>For a binary outcome <code>(y)</code>, if the model predicts probability <code>(p)</code> of <code>(y = 1)</code>, then the probability of observing <code>(y)</code> is:</p><ul><li><p>If <code>(y = 1):</code> probability is <code>(p)</code></p></li><li><p>If <code>(y = 0):</code> probability is <code>(1 - p)</code></p></li></ul><p>We can write both cases in one expression:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;P(y|p) = p^y (1-p)^{1-y}&quot;,&quot;id&quot;:&quot;RXKGUJUSHE&quot;}" data-component-name="LatexBlockToDOM"></div><p>Now training wants to choose parameters that make observed labels likely. That means maximizing the likelihood over all data points, or equivalently maximizing the log-likelihood (log is monotonic and turns products into sums).</p><p>For one example:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\log P(y|p) = \\log \\big( p^y (1-p)^{1-y} \\big) &quot;,&quot;id&quot;:&quot;GRHLUNINQQ&quot;}" data-component-name="LatexBlockToDOM"></div><p>Use <code>log</code> rules:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;= y \\log(p) \\cdot (1-y)\\log(1-p)&quot;,&quot;id&quot;:&quot;MIYHNWONPU&quot;}" data-component-name="LatexBlockToDOM"></div><p>To turn this into a loss we <em>minimize</em>, we negate it:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\ell(y,p) = -y \\log(p) -(1-y)\\log(1-p)&quot;,&quot;id&quot;:&quot;AOYCYEGBPQ&quot;}" data-component-name="LatexBlockToDOM"></div><p>That is the binary log loss.</p><p>Notice what it does: if <code>(y = 1)</code>, the loss is <code>(-log(p))</code>, which goes to infinity as <code>(p &#10141; 0)</code>. That&#8217;s the &#8220;<em>confidently wrong hurts a lot</em>&#8221; property, mathematically enforced.</p><h2>Worked example: log loss for two predictions</h2><p><strong>Problem.</strong> Compare losses for a correct-but-uncertain prediction and a correct-and-confident one.</p><p><strong>Given.</strong> True label <code>(y = 1)</code>. Two predictions: <code>(p&#8321; = 0.6)</code>, <code>(p&#8322; = 0.95)</code>.</p><p>When <code>(y = 1)</code>, loss is:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\ell = -\\log(p)&quot;,&quot;id&quot;:&quot;IPXRCWXNMT&quot;}" data-component-name="LatexBlockToDOM"></div><p>For <code>(p&#8321; = 0.6)</code>:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\ell_1 = -\\log(0.6) \\approx 0.5108&quot;,&quot;id&quot;:&quot;YBWYBWJLIL&quot;}" data-component-name="LatexBlockToDOM"></div><p>For <code>(p&#8322; = 0.95)</code>:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\ell_2 = -\\log(0.95) \\approx 0.0513&quot;,&quot;id&quot;:&quot;LHOSUALPDN&quot;}" data-component-name="LatexBlockToDOM"></div><p><strong>Meaning.</strong> Both are &#8220;<em>correct</em>&#8221; under a 0.5 threshold, but the confident correct prediction is rewarded much more (smaller loss). Training with this loss nudges the model to be not just correct, but <em>calibrated and decisive when the evidence supports it</em>.</p><h1>Reading the model: coefficients as directional pushes (with caveats)</h1><p>One of logistic regression&#8217;s most attractive traits is that it&#8217;s interpretable in a very practical sense. If you look at the learned coefficients:</p><ul><li><p>A positive <code>(w&#7522;)</code> means feature <code>(x&#7522;)</code> pushes probability toward &#8220;<em>yes</em>&#8221;.</p></li><li><p>A negative <code>(w&#7522;)</code> means it pushes toward &#8220;<em>no</em>&#8221;.</p></li><li><p>Larger magnitude generally means a stronger push.</p></li></ul><p>There&#8217;s also a deeper and very useful interpretation that connects directly to the evidence score. Logistic regression makes the evidence score linear:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;z = b + \\sum_i w_i x_i&quot;,&quot;id&quot;:&quot;CRMSTQPJAL&quot;}" data-component-name="LatexBlockToDOM"></div><p>And then:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;p = \\sigma(z)&quot;,&quot;id&quot;:&quot;OUMLUHNBDO&quot;}" data-component-name="LatexBlockToDOM"></div><p>Because the sigmoid is monotonic, increasing <code>(z)</code> always increases <code>(p)</code>. So coefficients literally control the direction of probability movement.</p><p>You will also hear a statement like: &#8220;<em>coefficients correspond to log-odds</em>&#8221;. That can be made explicit by solving the sigmoid for <code>(z)</code>.</p><p>Start from:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;p = \\frac{1}{1+e^{-z}}&quot;,&quot;id&quot;:&quot;NPOJWOBMHX&quot;}" data-component-name="LatexBlockToDOM"></div><p>Invert both sides:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\frac{1}{p} = 1 + e^{-z}&quot;,&quot;id&quot;:&quot;RPFZROHONV&quot;}" data-component-name="LatexBlockToDOM"></div><p>Subtract <code>1</code>:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\frac{1}{p} - 1 = e^{-z}&quot;,&quot;id&quot;:&quot;DXYRZBOOQN&quot;}" data-component-name="LatexBlockToDOM"></div><p>Combine terms:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\frac{1-p}{p} = e^{-z}&quot;,&quot;id&quot;:&quot;BMOUVYWUKM&quot;}" data-component-name="LatexBlockToDOM"></div><p>Take log:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\log\\Big(\\frac{1-p}{p}\\Big) = -z&quot;,&quot;id&quot;:&quot;UTEDZIBCAN&quot;}" data-component-name="LatexBlockToDOM"></div><p>Multiply by <code>(-1)</code>:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\log\\Big(\\frac{p}{1-p}\\Big) = z &quot;,&quot;id&quot;:&quot;GXCHKVDQNX&quot;}" data-component-name="LatexBlockToDOM"></div><p>So the evidence score <code>(z)</code> is the <strong>log-odds</strong>. Each feature contribution <code>(w&#7522; x&#7522;)</code> is a contribution to log-odds.</p><p>Now, the two gotchas that surprise beginners:</p><p><strong>Gotcha 1: feature scale matters.</strong> If one feature is measured in days <code>(0&#8211;365)</code> and another is a binary flag <code>(0/1)</code>, the day feature can have a small coefficient and still dominate the sum. Comparing raw coefficient magnitudes without standardizing features can be misleading.</p><p><strong>Gotcha 2: correlated features share credit.</strong> If two features are strongly correlated (say &#8220;<em>days since last login</em>&#8221; and &#8220;<em>number of sessions last month</em>&#8221;), the model can distribute weight between them in many equivalent ways. Individual coefficients may look unstable across retraining runs, even when predictions remain stable. Interpret coefficients with care: they are not always &#8220;<em>causal importance</em>&#8221;.</p><h1>What logistic regression can and cannot represent</h1><p>Logistic regression draws a boundary that is linear in feature space (or, said differently, it separates examples using a hyperplane in the original feature space). The probability changes smoothly as you move across that boundary.</p><p>That structure is a strength. It means:</p><ul><li><p><strong>Fast training.</strong> You can fit large datasets efficiently.</p></li><li><p><strong>Robustness.</strong> With regularization, it tends not to overfit wildly.</p></li><li><p><strong>A strong baseline.</strong> If you can&#8217;t beat logistic regression, you often don&#8217;t yet understand the problem or the features.</p></li><li><p><strong>Reasonable extrapolation.</strong> Linear evidence behaves predictably outside the training set (though not always correctly).</p></li></ul><p>But it is also a limitation. If the true relationship between features and outcome is highly non-linear - say, churn risk spikes only for a specific combination of behaviors, or fraud looks like a complicated &#8220;<em>island</em>&#8221; in feature space - then a single linear boundary may not capture it well.</p><p>There&#8217;s an important nuance: logistic regression is linear in the features you give it, not necessarily linear in the raw world. You can engineer features that expose non-linear structure. For example:</p><ul><li><p>Add polynomial terms like <code>(x&#178;)</code></p></li><li><p>Add interactions like <code>(x&#8321; x&#8322;)</code></p></li><li><p>Use splines or bucketed features</p></li></ul><p>Once you add those engineered features, logistic regression can represent more complex boundaries - but you paid for that complexity by choosing the right transformations.</p><p>In practice, this is why logistic regression often shines in domains with well-designed features (ads, ranking, many tabular problems). It&#8217;s not glamorous. It&#8217;s just honest about what it can represent: a smooth ramp from &#8220;<em>no</em>&#8221; to &#8220;<em>yes</em>&#8221; driven by additive evidence.</p><h1>When it fails in real systems: rare events, noisy labels, drifting populations</h1><p>Most textbook explanations end when the model is trained. Real problems start after deployment.</p><p><strong>Rare events.</strong> In fraud, serious adverse events, or rare diseases, positives may be 0.1% of the data. A logistic regression model can still output probabilities, but those probabilities can be poorly grounded if you evaluate incorrectly or if the model is pushed into regions with little positive data. You may see confident-looking numbers that are driven more by class imbalance and feature quirks than by true signal. Handling this often requires careful sampling strategies, appropriate metrics (like precision-recall curves), and explicit attention to calibration.</p><p><strong>Noisy labels.</strong> Suppose &#8220;<em>churn</em>&#8221; is defined as &#8220;<em>no activity for 30 days</em>&#8221;, but many users are seasonal and return later. Now your labels encode ambiguity. Logistic regression will respond by pushing probabilities toward the middle because the same feature patterns sometimes map to <code>1</code> and sometimes to <code>0</code>. That is not the model being &#8220;<em>weak</em>&#8221;; it is the model reflecting inconsistency in the target definition. If your organization expects crisp predictions from fuzzy labels, you will fight endlessly.</p><p><strong>Drifting populations.</strong> The most insidious failure is distribution shift. The model is trained on last year&#8217;s user behavior, but this year you introduced a new onboarding flow, a new pricing tier, or a competitor launched something disruptive. Now the relationship between features and churn changes. Your &#8220;<em>0.8</em>&#8221; probabilities may stop meaning &#8220;<em>80%</em>&#8221;. They might behave like &#8220;<em>60%</em>&#8221; in today&#8217;s world. That&#8217;s a calibration break caused by a moving target.</p><p>Operationally, this is why monitoring matters: not just accuracy, but calibration, feature distributions, and decision outcomes. Logistic regression is simple, but the system around it is not. The model&#8217;s humility - expressed as a probability - can be lost if you treat it like a deterministic oracle.</p><h1>Misunderstandings worth clearing up early</h1><p>A few confusions come up so often that it&#8217;s worth clearing them early, before they calcify into mental bugs.</p><p><strong>&#8220;Why is it called regression if it&#8217;s classification?&#8221;</strong> Historically, &#8220;<em>regression</em>&#8221; refers to modeling a numerical quantity. Logistic regression models a numerical quantity: the probability <code>(P(y=1|x))</code>. The <em>output</em> is continuous. We then optionally threshold it to get a class label. So the name is less wrong than it sounds; it&#8217;s just anchored in the probability-first view rather than the label-first view.</p><p><strong>&#8220;If the model says 0.9, does it know the answer?&#8221;</strong> No. A probability is not a promise about this individual case. It&#8217;s a statement about frequency among similar cases. If the model is well-calibrated, then among all cases where it predicts 0.9, about 90% should be positive. That&#8217;s a population-level claim, not a metaphysical certainty about one example.</p><p><strong>&#8220;Is 0.5 the default threshold?&#8221;</strong> It&#8217;s a default in the sense that it&#8217;s a convenient midpoint, but it&#8217;s rarely the <em>right</em> choice automatically. If false positives and false negatives have different costs (they almost always do), the optimal threshold can be far from <code>0.5</code>.</p><p><strong>&#8220;Does logistic regression output &#8216;</strong><em><strong>real probabilities</strong></em><strong>&#8217;?&#8221;</strong> It outputs numbers between 0 and 1 that are trained using a probability-based loss. Whether those numbers behave like real-world probabilities depends on calibration, data quality, and whether the deployment distribution matches training. Logistic regression is often reasonably calibrated compared to some more flexible models, but there are plenty of ways it can be miscalibrated in practice.</p><p>If you keep the probability-first mental model, these misunderstandings mostly dissolve. Confusion tends to enter when we treat the label as truth and the probability as a decoration, rather than the other way around.</p><div><hr></div><p><strong>&#128640; </strong><em><strong>Know someone who still finds logistic regression confusing?</strong></em></p><p>A simple mental model often helps more than another textbook explanation.</p><p>&#128257; <strong>Share this post</strong> with someone learning machine learning.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/logistic-regression-when-machines?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/logistic-regression-when-machines?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h1>Closing reflection: a small model with a big lesson</h1><p>Logistic regression is often introduced as a &#8220;<em>baseline classifier</em>&#8221;, which is technically true and psychologically unfair. It&#8217;s more than a baseline. It&#8217;s one of the cleanest examples of a principle that scales all the way up to modern machine learning systems:</p><p><strong>Separate belief from action.</strong></p><p>The model&#8217;s job is belief: given evidence, output an honest probability. Your system&#8217;s job is action: choose what to do given that belief, your costs, your risks, and your values. When you blur these two roles - when you treat a probability as a label, or a threshold as truth - you lose control. You also lose the ability to have clear conversations with stakeholders about trade-offs, because everything collapses into &#8220;<em>the model said so</em>&#8221;.</p><p>Logistic regression also teaches a quieter lesson about mathematics in ML: the formulas are not arbitrary. The sigmoid is not a random squashing function; it is a convenient, interpretable bridge between additive evidence (log-odds) and probabilities. Log loss is not a punishment invented to scare you; it falls directly out of maximum likelihood for a Bernoulli outcome, and it encodes a very human idea: confident wrongness should hurt.</p><p>If you later move to gradient-boosted trees, neural nets, or large language models, this framing still helps. You can ask: what is the model&#8217;s belief representation, how is it trained to be honest, and where do we convert beliefs into decisions? Logistic regression is small enough to fit in your head, but big enough to teach that habit well.</p><div><hr></div><ol><li><p><strong><a href="https://a.co/d/0dK0vp8Y">The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition</a></strong> <em>by Trevor Hastie, Robert Tibshirani, Jerome Friedman</em></p></li><li><p><strong><a href="https://a.co/d/00FoV7Fo">Machine Learning: A Probabilistic Perspective</a> </strong>(Adaptive Computation and Machine Learning series)<strong> </strong><em>by Kevin P. Murphy</em></p></li><li><p><strong><a href="https://a.co/d/02kYNKuh">Pattern Recognition and Machine Learning (Information Science and Statistics)</a></strong></p><p><em>by Christopher M. Bishop</em></p></li><li><p><strong><a href="https://a.co/d/0ihHFLok">Information Theory, Inference and Learning Algorithms</a> </strong><em>by David J. C. MacKay</em></p></li><li><p><strong><a href="https://cs229.stanford.edu/main_notes.pdf">Stanford CS229 notes (linear regression + optimization)</a> </strong><em>by Andrew Ng and Tengyu Ma</em></p></li><li><p><strong><a href="https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html#logisticregression">scikit-learn documentation for </a></strong><code>LogisticRegression</code></p></li></ol>]]></content:encoded></item><item><title><![CDATA[Thinking clearly in interviews — Add Two Numbers]]></title><description><![CDATA[Understanding the why before the code (Rust &#183; Python &#183; Scala)]]></description><link>https://iam.slys.dev/p/thinking-clearly-in-interviews-add</link><guid isPermaLink="false">https://iam.slys.dev/p/thinking-clearly-in-interviews-add</guid><dc:creator><![CDATA[Jakub Slys 🤖]]></dc:creator><pubDate>Mon, 09 Mar 2026 21:34:36 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!qdoY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b59c917-a9c8-4d45-9a35-74c829301c67_1536x1024.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_!qdoY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b59c917-a9c8-4d45-9a35-74c829301c67_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qdoY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b59c917-a9c8-4d45-9a35-74c829301c67_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!qdoY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b59c917-a9c8-4d45-9a35-74c829301c67_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!qdoY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b59c917-a9c8-4d45-9a35-74c829301c67_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!qdoY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b59c917-a9c8-4d45-9a35-74c829301c67_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qdoY!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b59c917-a9c8-4d45-9a35-74c829301c67_1536x1024.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4b59c917-a9c8-4d45-9a35-74c829301c67_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:3052385,&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://iam.slys.dev/i/187834298?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b59c917-a9c8-4d45-9a35-74c829301c67_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!qdoY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b59c917-a9c8-4d45-9a35-74c829301c67_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!qdoY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b59c917-a9c8-4d45-9a35-74c829301c67_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!qdoY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b59c917-a9c8-4d45-9a35-74c829301c67_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!qdoY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b59c917-a9c8-4d45-9a35-74c829301c67_1536x1024.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 role="img" 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><title></title><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>&#9888;&#65039; Before we begin &#8212; a leadership lens worth following</strong></p><div class="embedded-publication-wrap" data-attrs="{&quot;id&quot;:4640380,&quot;name&quot;:&quot;Leadership in Change&quot;,&quot;logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!nt6C!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc93a7f29-8673-4dd8-a435-838ade7e7337_560x560.png&quot;,&quot;base_url&quot;:&quot;https://leadershipinchange.com&quot;,&quot;hero_text&quot;:&quot;Don&#8217;t just read about AI, lead it. Get the weekly playbook for leaders who want to supercharge their expertise and multiply their impact.&quot;,&quot;author_name&quot;:&quot;Joel Salinas&quot;,&quot;show_subscribe&quot;:true,&quot;logo_bg_color&quot;:&quot;#fafafa&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="EmbeddedPublicationToDOMWithSubscribe"><div class="embedded-publication show-subscribe"><a class="embedded-publication-link-part" native="true" href="https://leadershipinchange.com?utm_source=substack&amp;utm_campaign=publication_embed&amp;utm_medium=web"><img class="embedded-publication-logo" src="https://substackcdn.com/image/fetch/$s_!nt6C!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc93a7f29-8673-4dd8-a435-838ade7e7337_560x560.png" width="56" height="56" style="background-color: rgb(250, 250, 250);"><span class="embedded-publication-name">Leadership in Change</span><div class="embedded-publication-hero-text">Don&#8217;t just read about AI, lead it. Get the weekly playbook for leaders who want to supercharge their expertise and multiply their impact.</div><div class="embedded-publication-author-name">By Joel Salinas</div></a><form class="embedded-publication-subscribe" method="GET" action="https://leadershipinchange.com/subscribe?"><input type="hidden" name="source" value="publication-embed"><input type="hidden" name="autoSubmit" value="true"><input type="email" class="email-input" name="email" placeholder="Type your email..."><input type="submit" class="button primary" value="Subscribe"></form></div></div><p><em><strong>Leadership in Change</strong> </em>by<em> </em><span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Joel Salinas&quot;,&quot;id&quot;:198127390,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!Uip2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ed5e6c5-5af1-4813-959c-4a1c14354fd2_500x500.png&quot;,&quot;uuid&quot;:&quot;d463d800-5ffa-4342-86b7-1ed222f9fbec&quot;}" data-component-name="MentionToDOM"></span> explores what it really means to lead through uncertainty, transformation, and complexity. It&#8217;s not motivational fluff - it&#8217;s grounded thinking about how leaders <em>adapt</em>, <em>influence</em>, and <em>evolve</em> when the environment shifts.</p><div><hr></div><p>You&#8217;re standing at a small bakery counter with a friend. You each grab a few items, and the cashier reads out totals in a way that feels slightly&#8230; backward. Instead of &#8220;<em>three dollars and forty-two cents</em>&#8221;, you hear &#8220;<em>two cents, then four dimes, then three dollars</em>&#8221;. Your brain stalls for a beat. You know it&#8217;s the same amount, but it&#8217;s being presented from the &#8220;<em>smallest</em>&#8221; part first.</p><p>Nothing is broken. It&#8217;s just an order you don&#8217;t usually use.</p><blockquote><p><strong>Problem</strong></p><p>You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order, and each of their nodes contains a single digit. Add the two numbers and return the sum as a linked list.</p><p>You may assume the two numbers do not contain any leading zero, except the number 0 itself.</p><p><strong>Examples</strong></p><p>Example 1:</p><p>Input: <code>l1 = [2,4,3]</code>, <code>l2 = [5,6,4]</code> Output: <code>[7,0,8]</code> Explanation: <code>342 + 465 = 807</code>.</p><p>Example 2:</p><p>Input: <code>l1 = [0]</code>, <code>l2 = [0]</code> Output: <code>[0]</code></p><p>Example 3:</p><p>Input: <code>l1 = [9,9,9,9,9,9,9]</code>, <code>l2 = [9,9,9,9]</code> Output: <code>[8,9,9,9,0,0,0,1]</code></p><p><strong>Constraints</strong></p><ul><li><p>The number of nodes in each linked list is in the range <code>[1, 100].</code></p></li><li><p>0 &lt;= node value &lt;= 9</p></li><li><p>It is guaranteed that the list represents a number that does not have leading zeros.</p></li></ul></blockquote><p>If you&#8217;ve ever counted out change from coins to bills, you&#8217;ve actually done this: you start with the smallest units, deal with carry (ten pennies make a dime), and only then move up. The process is natural. The representation is what&#8217;s unusual.</p><p>That tiny moment - &#8220;<em>wait, what order am I seeing this in</em>?&#8221; - is the entire heart of a famous coding interview problem. You&#8217;re given two numbers, but you don&#8217;t get them as normal integers. You get them as linked lists whose digits arrive least-significant first. Your job is to add them and return the result in the same &#8220;<em>backward</em>&#8221; form.</p><p>Interviewers like this because it&#8217;s not about advanced math. It&#8217;s about whether you can stay calm when the data format is unfamiliar, translate it into a process you already understand (grade-school addition), and implement it cleanly without tripping over edge cases. Under time pressure, the winner isn&#8217;t the person who&#8217;s seen the trick - it&#8217;s the person who can recognize that there isn&#8217;t a trick.</p><h1>&#127897;&#65039; Why interviewers like this problem</h1><p>From an interviewer&#8217;s perspective, <em>Add Two Numbers</em> is a compact test of a lot of real engineering skills.</p><p>First, it tests whether you can map a concept to a representation. Adding numbers is easy; adding numbers when the digits are stored in a linked list - reversed - is where candidates reveal how quickly they can normalize a problem. Strong candidates don&#8217;t complain about the format; they convert it into a mental model (&#8220;<em>this is just digit-by-digit addition with carry</em>&#8221;).</p><p>Second, it exposes your relationship with pointers/references and incremental construction. Linked lists are intentionally a little awkward: you can&#8217;t index, you can&#8217;t easily go backward, and you need to build results node by node. The problem forces you into iterative thinking, careful state management, and clean handling of &#8220;<em>end of list</em>&#8221; conditions.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!QEuU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18dcf4b7-d23a-4e49-9423-2c672f93e460_2330x1273.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QEuU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18dcf4b7-d23a-4e49-9423-2c672f93e460_2330x1273.png 424w, https://substackcdn.com/image/fetch/$s_!QEuU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18dcf4b7-d23a-4e49-9423-2c672f93e460_2330x1273.png 848w, https://substackcdn.com/image/fetch/$s_!QEuU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18dcf4b7-d23a-4e49-9423-2c672f93e460_2330x1273.png 1272w, https://substackcdn.com/image/fetch/$s_!QEuU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18dcf4b7-d23a-4e49-9423-2c672f93e460_2330x1273.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QEuU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18dcf4b7-d23a-4e49-9423-2c672f93e460_2330x1273.png" width="1456" height="795" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/18dcf4b7-d23a-4e49-9423-2c672f93e460_2330x1273.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:795,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:177357,&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://iam.slys.dev/i/187834298?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18dcf4b7-d23a-4e49-9423-2c672f93e460_2330x1273.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_!QEuU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18dcf4b7-d23a-4e49-9423-2c672f93e460_2330x1273.png 424w, https://substackcdn.com/image/fetch/$s_!QEuU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18dcf4b7-d23a-4e49-9423-2c672f93e460_2330x1273.png 848w, https://substackcdn.com/image/fetch/$s_!QEuU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18dcf4b7-d23a-4e49-9423-2c672f93e460_2330x1273.png 1272w, https://substackcdn.com/image/fetch/$s_!QEuU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18dcf4b7-d23a-4e49-9423-2c672f93e460_2330x1273.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 role="img" 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><title></title><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>Third, it&#8217;s a communication problem disguised as an algorithm problem. In a live interview, you&#8217;re expected to narrate your reasoning: what variables you&#8217;re tracking, why carry matters, what happens when one list is longer, and what you do at the end if there&#8217;s still carry left.</p><p>Finally, it&#8217;s a safe place to evaluate code quality. There&#8217;s no need for fancy optimizations, but there&#8217;s plenty of room for messy code: off-by-one mistakes, null handling bugs, unnecessary conversions, and overly clever approaches that hide correctness issues. Interviewers want to see whether you can write code that is both correct and readable when you&#8217;re being watched.</p><h1>&#128214; Understanding the problem in plain language</h1><p>You&#8217;re given two singly linked lists. Each node holds one digit <code>(0&#8211;9)</code>. If you read the list from head to tail, you&#8217;re reading the number from least significant digit to most significant digit.</p><p>So the list <code>[2, 4, 3]</code> represents the number 342, because:</p><ul><li><p>head <code>2</code> is the ones place</p></li><li><p>then <code>4</code> is the tens place</p></li><li><p>then <code>3</code> is the hundreds place</p></li></ul><p>You need to add the two numbers represented by the two lists and return a new linked list representing their sum in the same reversed-digit format.</p><p>A few important clarifications that are easy to miss when you&#8217;re nervous:</p><ul><li><p>The lists are <strong>non-empty</strong>. You&#8217;ll always have at least one node in each.</p></li><li><p>Digits are <strong>non-negative single digits</strong>. No node contains <code>12</code> or <code>-1</code>.</p></li><li><p>The numbers have <strong>no leading zeros</strong> in the normal representation, but that&#8217;s not the main challenge here. (And <code>0</code> itself is allowed.)</p></li><li><p>The result can be longer than either input list, because addition can introduce a new most-significant digit (like <code>999 + 1 = 1000</code>).</p></li></ul><p>The most important mental shift is this: you do <em>not</em> need to convert the lists to integers. In fact, you usually shouldn&#8217;t. The natural solution is to simulate grade-school addition as you walk the lists.</p><h1>&#128099; Reasoning through examples</h1><p>Let&#8217;s walk through the classic example slowly, the way you&#8217;d narrate it in an interview.</p><p><code>l1 = [2, 4, 3]</code> represents <code>342</code><br><code>l2 = [5, 6, 4]</code> represents <code>465</code></p><p>We add digit by digit, starting from the head (ones place), carrying when needed.</p><ul><li><p>Start with <code>carry = 0</code>.</p></li><li><p>Ones place: <code>2 + 5 + 0 = 7</code> &#8594; write down 7, carry 0.</p></li><li><p>Tens place: <code>4 + 6 + 0 = 10</code> &#8594; write down 0, carry 1.</p></li><li><p>Hundreds place: <code>3 + 4 + 1 = 8</code> &#8594; write down 8, carry 0.</p></li><li><p>Done, <code>carry is 0</code>, so stop.</p></li></ul><p>Result: <code>[7, 0, 8]</code> which represents 807. That matches what we expect.</p><p>Now look at an example where carry survives past the last digits:</p><p><code>l1 = [9, 9, 9, 9, 9, 9, 9]</code><br><code>l2 = [9, 9, 9, 9]</code></p><p>Here&#8217;s how you should describe your thinking out loud:</p><ul><li><p>&#8220;<em>I&#8217;m going to traverse both lists until both are exhausted and there&#8217;s no carry.</em>&#8221;</p></li><li><p>&#8220;<em>At each position, if a list is exhausted, I treat its digit as 0.</em>&#8221;</p></li><li><p>&#8220;<em>I compute sum = digit1 + digit2 + carry, output sum % 10, and update carry = sum // 10.</em>&#8221;</p></li></ul><p>If you narrate it like that, you&#8217;ll naturally handle unequal lengths and the final carry without special-case hacks.</p><p>Where intuition often fails: candidates sometimes stop when both pointers are <code>null</code> and forget about a remaining carry. Or they try to handle carry with complicated branching instead of one consistent formula. The formula is your anchor under pressure.</p><h1>&#128207; Constraints and what they tell us</h1><p>The lists have between 1 and 100 nodes each. That&#8217;s small, but don&#8217;t let it trick you into sloppy thinking.</p><p>In interviews, constraints are less about &#8220;<em>do we need an </em><code>O(n log n)</code><em> trick?</em>&#8221; and more about &#8220;<em>what approaches are appropriate and safe?</em>&#8221;</p><p>Here&#8217;s what the constraints imply:</p><ul><li><p><strong>Time complexity</strong>: a single pass over both lists is obviously fine. The natural solution is <code>O(max(m, n))</code>.</p></li><li><p><strong>Space complexity</strong>: you need a result list, so <code>O(max(m, n))</code> additional nodes is unavoidable. Beyond that, you should be <code>O(1)</code> extra space.</p></li><li><p><strong>Avoid integer conversion</strong>: even though 100 digits could fit in big integers in some languages, converting is usually considered a red flag in interviews. It dodges the linked-list aspect and can introduce overflow issues in languages without arbitrary precision.</p></li><li><p><strong>Input size isn&#8217;t huge, but correctness still matters</strong>: 100 nodes is enough to expose bugs in carry logic, termination conditions, and list construction.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!eTdq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89df6594-ce18-4408-9d12-35ff0151b976_2700x2484.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eTdq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89df6594-ce18-4408-9d12-35ff0151b976_2700x2484.png 424w, https://substackcdn.com/image/fetch/$s_!eTdq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89df6594-ce18-4408-9d12-35ff0151b976_2700x2484.png 848w, https://substackcdn.com/image/fetch/$s_!eTdq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89df6594-ce18-4408-9d12-35ff0151b976_2700x2484.png 1272w, https://substackcdn.com/image/fetch/$s_!eTdq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89df6594-ce18-4408-9d12-35ff0151b976_2700x2484.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!eTdq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89df6594-ce18-4408-9d12-35ff0151b976_2700x2484.png" width="1456" height="1340" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/89df6594-ce18-4408-9d12-35ff0151b976_2700x2484.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1340,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:447341,&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://iam.slys.dev/i/187834298?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89df6594-ce18-4408-9d12-35ff0151b976_2700x2484.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_!eTdq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89df6594-ce18-4408-9d12-35ff0151b976_2700x2484.png 424w, https://substackcdn.com/image/fetch/$s_!eTdq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89df6594-ce18-4408-9d12-35ff0151b976_2700x2484.png 848w, https://substackcdn.com/image/fetch/$s_!eTdq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89df6594-ce18-4408-9d12-35ff0151b976_2700x2484.png 1272w, https://substackcdn.com/image/fetch/$s_!eTdq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89df6594-ce18-4408-9d12-35ff0151b976_2700x2484.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 role="img" 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><title></title><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>Interviewers also use these constraints as a gentle prompt: &#8220;<em>This is meant to be straightforward</em>&#8221;. If you find yourself designing stacks, recursion, or complex data structures, pause and ask whether you&#8217;re solving a different problem than the one you were given.</p><h1>&#129300; The obvious first idea &#8212; and why it&#8217;s not enough</h1><p>The most common first idea is: &#8220;<em>Convert each linked list into an integer, add them, then convert back</em>&#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_!DLCB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a4d2505-fa67-47f9-8d05-c4bfde0fc494_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!DLCB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a4d2505-fa67-47f9-8d05-c4bfde0fc494_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!DLCB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a4d2505-fa67-47f9-8d05-c4bfde0fc494_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!DLCB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a4d2505-fa67-47f9-8d05-c4bfde0fc494_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!DLCB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a4d2505-fa67-47f9-8d05-c4bfde0fc494_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!DLCB!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a4d2505-fa67-47f9-8d05-c4bfde0fc494_1536x1024.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4a4d2505-fa67-47f9-8d05-c4bfde0fc494_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:763023,&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://iam.slys.dev/i/187834298?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a4d2505-fa67-47f9-8d05-c4bfde0fc494_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!DLCB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a4d2505-fa67-47f9-8d05-c4bfde0fc494_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!DLCB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a4d2505-fa67-47f9-8d05-c4bfde0fc494_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!DLCB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a4d2505-fa67-47f9-8d05-c4bfde0fc494_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!DLCB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a4d2505-fa67-47f9-8d05-c4bfde0fc494_1536x1024.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 role="img" 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><title></title><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>It feels natural because that&#8217;s how humans add numbers: we think of whole numbers, not lists of digits. And in a scripting language with big integers, it might even work for these constraints.</p><p>But in interviews, this approach is usually not enough for three reasons:</p><p>First, it ignores what&#8217;s being tested. The problem is deliberately built around linked list traversal, incremental output construction, and carry handling. If you convert to integers, you&#8217;re side-stepping the core skill signal.</p><p>Second, it can be unsafe or awkward across languages. In many environments (or in lower-level languages), integers have fixed size. A 100-digit number will overflow any standard 64-bit type. You could use big integer libraries, but now your &#8220;<em>simple</em>&#8221; solution depends on library availability and adds noise to the interview.</p><p>Third, conversion introduces its own pitfalls: building strings, reversing, parsing, and then reconstructing the list. You end up with more code, more failure modes, and less clarity.</p><p>A strong candidate will often acknowledge the naive approach quickly - &#8220;<em>We could convert, but that risks overflow and misses the point</em>&#8221; - and then pivot to the real approach: simulate addition directly on the lists.</p><p>That pivot is an interview moment. It shows you can evaluate trade-offs rather than blindly implementing the first thought.</p><h1>&#128161; The key insight</h1><p>The key insight is that the &#8220;<em>reverse order</em>&#8221; representation is not a complication - it&#8217;s a gift.</p><p>If digits were stored most-significant first, you&#8217;d have a real problem: addition starts from the least-significant digit, so you&#8217;d need to reverse lists, use stacks, or recurse to reach the tail first.</p><p>But this problem hands you the digits starting from the least-significant place. That means you can add as you traverse, exactly like counting change from coins upward. No lookahead, no backtracking.</p><p>Once you accept that, the algorithm becomes almost mechanical:</p><ul><li><p>Maintain a <code>carry</code>.</p></li><li><p>Walk both lists in lockstep.</p></li><li><p>At each position, read the current digit from each list (or 0 if that list is finished).</p></li><li><p>Compute <code>sum = d1 + d2 + carry</code>.</p></li><li><p>Output <code>sum % 10</code>.</p></li><li><p>Update <code>carry = sum // 10</code>.</p></li><li><p>Continue until both lists are finished and <code>carry == 0</code>.</p></li></ul><p>This insight also tells you how to structure your code cleanly: one loop, one consistent update rule, and a dummy head node to simplify list construction.</p><p>In interviews, &#8220;<code>dummy head</code>&#8221; is often a differentiator. It&#8217;s not advanced, but it signals you&#8217;ve built lists before and you know how to avoid special-casing the first node.</p><div><hr></div><h3>&#128161; Did this mental shift click for you?</h3><p>What was your &#8220;<em>aha</em>&#8221; moment while reading this?</p><p>&#128172; Leave a comment - I&#8217;d love to know how you think about Add Two Numbers.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/thinking-clearly-in-interviews-add/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/thinking-clearly-in-interviews-add/comments"><span>Leave a comment</span></a></p><div><hr></div><h1>&#9881;&#65039; The final approach</h1><p>Narratively, here&#8217;s the approach you want to be able to explain smoothly:</p><p>You create a new linked list for the result. You keep a pointer (<code>tail</code>) to the last node in the result so you can append efficiently. You traverse <code>l1</code> and <code>l2</code> with pointers <code>p</code> and <code>q</code>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!D7pa!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1ca18b0-dc37-48ec-a054-a18b9f9b433e_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!D7pa!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1ca18b0-dc37-48ec-a054-a18b9f9b433e_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!D7pa!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1ca18b0-dc37-48ec-a054-a18b9f9b433e_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!D7pa!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1ca18b0-dc37-48ec-a054-a18b9f9b433e_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!D7pa!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1ca18b0-dc37-48ec-a054-a18b9f9b433e_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!D7pa!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1ca18b0-dc37-48ec-a054-a18b9f9b433e_1536x1024.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b1ca18b0-dc37-48ec-a054-a18b9f9b433e_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1312780,&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://iam.slys.dev/i/187834298?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1ca18b0-dc37-48ec-a054-a18b9f9b433e_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!D7pa!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1ca18b0-dc37-48ec-a054-a18b9f9b433e_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!D7pa!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1ca18b0-dc37-48ec-a054-a18b9f9b433e_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!D7pa!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1ca18b0-dc37-48ec-a054-a18b9f9b433e_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!D7pa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1ca18b0-dc37-48ec-a054-a18b9f9b433e_1536x1024.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 role="img" 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><title></title><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>At each iteration:</p><ul><li><p>Let <code>x</code> be <code>p.val</code> if <code>p</code> exists, otherwise 0.</p></li><li><p>Let <code>y</code> be <code>q.val</code> if <code>q</code> exists, otherwise 0.</p></li><li><p>Let <code>s = x + y + carry</code>.</p></li><li><p>The digit to store is <code>s % 10</code>.</p></li><li><p>The next carry is <code>s / 10</code> (integer division).</p></li></ul><p>Append the digit to the result, move <code>p</code> and <code>q</code> forward if they exist, and repeat.</p><p>Correctness argument (the kind interviewers like):</p><ul><li><p>At each step you compute the correct digit for that place value because you include the carry from the previous place.</p></li><li><p>Carry is always 0 or 1 (since max digit sum is <code>9 + 9 + 1 = 19</code>), so it&#8217;s safe and bounded.</p></li><li><p>You terminate only when there are no digits left in either input and no carry left to propagate, ensuring the most-significant carry is not lost.</p></li></ul><p>Edge cases are naturally handled:</p><ul><li><p>One list longer than the other &#8594; missing digits treated as 0.</p></li><li><p>Final carry after both lists end &#8594; loop continues and appends it.</p></li><li><p>Inputs are <code>[0]</code> and <code>[0]</code> &#8594; result becomes <code>[0]</code>.</p></li></ul><p>This is the kind of solution that stays stable under pressure because it has one moving part: the carry and the loop.</p><h2>&#9201;&#65039; Performance under interview constraints</h2><p>Time complexity is <code>O(max(m, n))</code>. You touch each node in each list once, and do O(1) work per node.</p><p>Space complexity is <code>O(max(m, n))</code> for the output list. Extra working space (not counting the output) is <code>O(1)</code>: a few pointers and integers.</p><p>In a live interview, you should justify complexity in plain language:</p><ul><li><p>&#8220;<em>We traverse both lists once, so runtime is linear in the length of the longer list.</em>&#8221;</p></li><li><p>&#8220;<em>We allocate one node per digit in the result, which is at most one more than the longer input due to carry.</em>&#8221;</p></li></ul><p>Trade-offs are minimal here, but you can still show maturity by stating what you&#8217;re <em>not</em> doing:</p><ul><li><p>&#8220;<em>I&#8217;m not converting to integers to avoid overflow and unnecessary work.</em>&#8221;</p></li><li><p>&#8220;<em>I&#8217;m not using recursion because iteration is simpler and avoids stack depth concerns.</em>&#8221;</p></li></ul><p>That&#8217;s often enough to signal strong judgment without over-explaining.</p><h1>&#128187; Implementation</h1><p>Implementation is secondary to clarity of thought, but in interviews, correctness and readability are non-negotiable. The easiest way to write clean code here is:</p><ul><li><p>Use a dummy head node.</p></li><li><p>Keep a <code>tail</code> pointer for appending.</p></li><li><p>Use a loop condition that includes carry: <code>while p != null or q != null or carry != 0</code>.</p></li></ul><p>Also, keep your variable names boring. &#8220;<em>carry</em>&#8221;, &#8220;<em>dummy</em>&#8221;, &#8220;<em>tail</em>&#8221;, &#8220;<em>p</em>&#8221;, &#8220;<em>q</em>&#8221; are boring in a good way: they reduce cognitive load for both you and the interviewer.</p><div><hr></div><h3>&#9888;&#65039; Know someone preparing for interviews?</h3><p>Send this to them - it might save them from an avoidable mistake.</p><p>&#128257; Share this post with a friend grinding interview prep.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/thinking-clearly-in-interviews-add?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/thinking-clearly-in-interviews-add?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2>&#128013; Python implementation</h2><p>In Python, the implementation reads very close to the algorithm. The main detail is defining a <code>ListNode</code> class and carefully moving pointers.</p><pre><code>from __future__ import annotations
from typing import Optional

class ListNode:
    def __init__(self, val: int = 0, next: Optional[&#8221;ListNode&#8221;] = None):
        self.val = val
        self.next = next

def addTwoNumbers(l1: ListNode, l2: ListNode) -&gt; ListNode:
    dummy = ListNode(0)
    tail = dummy

    carry = 0
    p, q = l1, l2

    while p is not None or q is not None or carry != 0:
        x = p.val if p is not None else 0
        y = q.val if q is not None else 0

        s = x + y + carry
        digit = s % 10
        carry = s // 10

        tail.next = ListNode(digit)
        tail = tail.next

        if p is not None:
            p = p.next
        if q is not None:
            q = q.next

    return dummy.next</code></pre><p>A couple of interview-friendly notes you can say while writing:</p><ul><li><p>&#8220;<em>The dummy node avoids a special case for the head of the result list.</em>&#8221;</p></li><li><p>&#8220;<em>The loop condition includes carry so we don&#8217;t drop a final carry digit.</em>&#8221;</p></li><li><p>&#8220;<em>When one list ends, I treat its digit as 0.</em>&#8221;</p></li></ul><p>If you want to be extra careful, you can mention that the algorithm supports <code>[0] + [0]</code> naturally, and that digits are guaranteed 0&#8211;9 so carry stays bounded.</p><h2>&#129408; Rust implementation</h2><p>Rust adds two kinds of pressure: ownership and the <code>Option&lt;Box&lt;ListNode&gt;&gt;</code> shape. The trick is not to fight it. Use references to traverse (<code>as_ref()</code>), and build the output list with a mutable tail pointer.</p><p>Below is a common, readable pattern: we keep <code>p</code> and <code>q</code> as <code>Option&lt;&amp;Box&lt;ListNode&gt;&gt;</code> (borrowed traversal), while we build the result list as owned nodes.</p><pre><code>#[derive(PartialEq, Eq, Clone, Debug)]
pub struct ListNode {
    pub val: i32,
    pub next: Option&lt;Box&lt;ListNode&gt;&gt;,
}

impl ListNode {
    #[inline]
    pub fn new(val: i32) -&gt; Self {
        ListNode { val, next: None }
    }
}

pub fn add_two_numbers(
    l1: Option&lt;Box&lt;ListNode&gt;&gt;,
    l2: Option&lt;Box&lt;ListNode&gt;&gt;,
) -&gt; Option&lt;Box&lt;ListNode&gt;&gt; {
    let mut carry: i32 = 0;

    // Borrowed pointers for traversal (we don&#8217;t need to mutate inputs).
    let mut p = l1.as_ref();
    let mut q = l2.as_ref();

    // Dummy head for output.
    let mut dummy = Box::new(ListNode::new(0));
    let mut tail = &amp;mut dummy;

    while p.is_some() || q.is_some() || carry != 0 {
        let x = p.map(|n| n.val).unwrap_or(0);
        let y = q.map(|n| n.val).unwrap_or(0);

        let s = x + y + carry;
        let digit = s % 10;
        carry = s / 10;

        tail.next = Some(Box::new(ListNode::new(digit)));
        tail = tail.next.as_mut().unwrap();

        p = p.and_then(|n| n.next.as_ref());
        q = q.and_then(|n| n.next.as_ref());
    }

    dummy.next
}</code></pre><p>What to point out in an interview:</p><ul><li><p>We traverse by borrowing (<code>as_ref()</code>), which avoids moving ownership out of <code>l1</code>/<code>l2</code> during the loop.</p></li><li><p>We use a dummy head and a mutable reference <code>tail</code> to append in <code>O(1)</code>.</p></li><li><p><code>tail.next.as_mut().unwrap()</code> is safe here because we just set <code>tail.next</code> to <code>Some(...)</code>.</p></li></ul><p>If the interviewer asks about safety: integer operations are safe here because values are tiny (<code>0..9</code> plus carry), so no overflow concerns with <code>i32</code>.</p><h2>&#128995; Scala implementation</h2><p>In Scala, you typically model a linked list node with a class containing <code>var next</code> so you can build incrementally. The core logic remains the same: traverse, compute digit and carry, append.</p><pre><code>final class ListNode(var value: Int, var next: ListNode = null)

object Solution {
  def addTwoNumbers(l1: ListNode, l2: ListNode): ListNode = {
    val dummy = new ListNode(0)
    var tail = dummy

    var carry = 0
    var p = l1
    var q = l2

    while (p != null || q != null || carry != 0) {
      val x = if (p != null) p.value else 0
      val y = if (q != null) q.value else 0

      val s = x + y + carry
      val digit = s % 10
      carry = s / 10

      tail.next = new ListNode(digit)
      tail = tail.next

      if (p != null) p = p.next
      if (q != null) q = q.next
    }

    dummy.next
  }
}</code></pre><p>Design choices worth mentioning:</p><ul><li><p>This is intentionally iterative: it&#8217;s simpler and avoids recursion depth concerns.</p></li><li><p><code>dummy</code> and <code>tail</code> keep the append logic clean.</p></li><li><p>Using <code>null</code> for list termination is common when mirroring interview-style list node definitions; in production Scala you might prefer <code>Option</code>, but that adds verbosity that often isn&#8217;t helpful in a timed setting.</p></li></ul><h1>&#9888;&#65039; Common interview mistakes</h1><p>People rarely fail this problem because they don&#8217;t know how to add numbers. They fail because they lose control of the small moving parts while talking and coding at the same time.</p><p>Forgetting the final carry is the classic one. You get a correct-looking list for many inputs, but you break on things like <code>[5] + [5]</code> (should produce <code>[0, 1]</code>). The cure is structural: bake carry into the loop condition. Don&#8217;t try to &#8220;remember&#8221; to handle it afterward.</p><p>Mismanaging list traversal is another. Candidates sometimes advance pointers too early, or they read <code>p.val</code> without checking <code>p != null</code>. Again, the cure is to adopt a stable pattern: read digits with conditional expressions, then advance pointers at the end of the loop.</p><p>Building the result list with special cases is also common: &#8220;<em>If head is null set head, else append&#8230;</em>&#8221;. Under pressure, that&#8217;s where bugs breed. Dummy head is the antidote because it makes every append identical.</p><p>Finally, over-complicating the solution can be its own failure mode. If you find yourself reversing lists, creating stacks, or converting to strings, pause. Ask: &#8220;<em>Am I still doing digit-by-digit addition?</em>&#8221; If not, you&#8217;re probably leaving the clean path.</p><h1>&#128269; Edge cases interviewers love to ask about</h1><p>Interviewers often probe edge cases not to be tricky, but to see whether your solution is robust and whether you can reason about it calmly.</p><p>One list is much longer than the other is a favorite. For example: <code>[1] + [9,9,9]</code>. The correct behavior is to keep going after the shorter list ends and treat its digits as 0. Your loop condition and digit extraction should already handle this.</p><p>A final carry that extends the result is another standard check: <code>[9,9] + [1]</code> should yield <code>[0,0,1]</code>. When asked, you want to respond with confidence: &#8220;My loop continues while carry is non-zero, so it appends an extra node when needed.&#8221;</p><p>Inputs containing zeros are also asked, especially <code>[0] + [0]</code>. Some buggy solutions accidentally return an empty list or skip node creation. With the dummy-head approach, this case is naturally fine.</p><p>Occasionally, an interviewer asks about mutating inputs: &#8220;<em>Can you reuse nodes?</em>&#8221; In most interview settings, returning a new list is the expected approach. If asked, you can say: &#8220;<em>We could reuse nodes to reduce allocations, but it complicates the code and risks modifying inputs unexpectedly; I&#8217;d stick with a fresh list unless explicitly asked.</em>&#8221;</p><p>And sometimes they ask the &#8220;<em>what if</em>&#8221; variant: digits stored in forward order. The correct response is not to panic - it&#8217;s to identify the difference: forward order prevents left-to-right addition, so you&#8217;d need to reverse lists, use stacks, or use recursion. The important part is that you can articulate the dependency: <em>addition wants least-significant digits first</em>.</p><h1>&#127891; What this problem trains you to do</h1><p>This problem trains a very transferable interview skill: <strong>staying oriented when the representation is unfamiliar</strong>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!UfgY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba1a7e23-91f7-400c-8b41-e332c92ed7b6_2174x1049.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UfgY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba1a7e23-91f7-400c-8b41-e332c92ed7b6_2174x1049.png 424w, https://substackcdn.com/image/fetch/$s_!UfgY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba1a7e23-91f7-400c-8b41-e332c92ed7b6_2174x1049.png 848w, https://substackcdn.com/image/fetch/$s_!UfgY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba1a7e23-91f7-400c-8b41-e332c92ed7b6_2174x1049.png 1272w, https://substackcdn.com/image/fetch/$s_!UfgY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba1a7e23-91f7-400c-8b41-e332c92ed7b6_2174x1049.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!UfgY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba1a7e23-91f7-400c-8b41-e332c92ed7b6_2174x1049.png" width="1456" height="703" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ba1a7e23-91f7-400c-8b41-e332c92ed7b6_2174x1049.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:703,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:136003,&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://iam.slys.dev/i/187834298?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba1a7e23-91f7-400c-8b41-e332c92ed7b6_2174x1049.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_!UfgY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba1a7e23-91f7-400c-8b41-e332c92ed7b6_2174x1049.png 424w, https://substackcdn.com/image/fetch/$s_!UfgY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba1a7e23-91f7-400c-8b41-e332c92ed7b6_2174x1049.png 848w, https://substackcdn.com/image/fetch/$s_!UfgY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba1a7e23-91f7-400c-8b41-e332c92ed7b6_2174x1049.png 1272w, https://substackcdn.com/image/fetch/$s_!UfgY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba1a7e23-91f7-400c-8b41-e332c92ed7b6_2174x1049.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 role="img" 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><title></title><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>In real engineering, data is rarely handed to you in the ideal shape. It&#8217;s serialized, chunked, streamed, reversed, sparse, or wrapped in an API that forces a certain access pattern. The winning move is often to stop thinking &#8220;<em>this is weird</em>&#8221; and start thinking &#8220;<em>what process does this representation make natural?</em>&#8221;</p><p>Here, reverse-order digits make carry-based addition natural. You don&#8217;t need to fight the structure. You lean into it.</p><p>It also trains incremental construction and pointer discipline - skills that show up in many classic tasks: merging sorted lists, removing nodes, partitioning lists, building trees iteratively, and streaming algorithms where you produce output as you consume input.</p><p>Most importantly, it trains a style of reasoning that interviewers trust: a stable loop invariant (&#8220;<em>I&#8217;ve computed all digits up to this position correctly, carry represents overflow to the next position</em>&#8221;), a simple termination condition, and small, repeatable operations.</p><p>When you can explain that clearly, you&#8217;re not just &#8220;<em>solving the problem</em>&#8221;. You&#8217;re demonstrating that you can think like an engineer under observation.</p><h1>&#127793; Closing thoughts</h1><p>There&#8217;s a quiet confidence that comes from problems like this - not because they&#8217;re hard, but because they reward steadiness. The representation is a little unusual, and that&#8217;s enough to trigger doubt in the moment. The way through is to recognize the familiar process hiding underneath: add digits, carry, repeat.</p><p>If you practice explaining this solution out loud - carry logic, loop condition, why dummy head simplifies construction - you&#8217;ll find that the code almost writes itself. And that&#8217;s the real goal for live interviews: reduce the number of decisions you have to make while someone is watching.</p><div><hr></div><h3>&#129504; If you want to build real interview intuition&#8230;</h3><p>I write deep, calm breakdowns of classic problems - without tricks or memorization.</p><p>&#128236; Subscribe to get the next one directly.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/subscribe?"><span>Subscribe now</span></a></p>]]></content:encoded></item><item><title><![CDATA[How Load Balancing really works — and why it is not just about splitting traffic]]></title><description><![CDATA[System design fundamentals]]></description><link>https://iam.slys.dev/p/how-load-balancing-really-works-and</link><guid isPermaLink="false">https://iam.slys.dev/p/how-load-balancing-really-works-and</guid><dc:creator><![CDATA[Jakub Slys 🤖]]></dc:creator><pubDate>Tue, 03 Mar 2026 21:43:24 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!t6fh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5441de9a-4a85-4939-9186-7106fbaeffae_1536x1024.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_!t6fh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5441de9a-4a85-4939-9186-7106fbaeffae_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!t6fh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5441de9a-4a85-4939-9186-7106fbaeffae_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!t6fh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5441de9a-4a85-4939-9186-7106fbaeffae_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!t6fh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5441de9a-4a85-4939-9186-7106fbaeffae_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!t6fh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5441de9a-4a85-4939-9186-7106fbaeffae_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!t6fh!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5441de9a-4a85-4939-9186-7106fbaeffae_1536x1024.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5441de9a-4a85-4939-9186-7106fbaeffae_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2449540,&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://iam.slys.dev/i/176401638?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5441de9a-4a85-4939-9186-7106fbaeffae_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!t6fh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5441de9a-4a85-4939-9186-7106fbaeffae_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!t6fh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5441de9a-4a85-4939-9186-7106fbaeffae_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!t6fh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5441de9a-4a85-4939-9186-7106fbaeffae_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!t6fh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5441de9a-4a85-4939-9186-7106fbaeffae_1536x1024.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 role="img" 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><title></title><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>&#9888;&#65039; <strong>Before we dive in &#8212; highly worth your attention</strong></p><div class="embedded-publication-wrap" data-attrs="{&quot;id&quot;:4097137,&quot;name&quot;:&quot;Product with Attitude&quot;,&quot;logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!KJxv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f411cce-3771-42d9-965e-1c01efe464eb_986x986.png&quot;,&quot;base_url&quot;:&quot;https://karozieminski.substack.com&quot;,&quot;hero_text&quot;:&quot;AI Product Manager turning everyone into AI builders. I help you design, build and test your product, and feature it on StackShelf.app. I connect you with a supportive 10K+ community building and learning in public.&quot;,&quot;author_name&quot;:&quot;Karo (Product with Attitude)&quot;,&quot;show_subscribe&quot;:true,&quot;logo_bg_color&quot;:&quot;#ffffff&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="EmbeddedPublicationToDOMWithSubscribe"><div class="embedded-publication show-subscribe"><a class="embedded-publication-link-part" native="true" href="https://karozieminski.substack.com?utm_source=substack&amp;utm_campaign=publication_embed&amp;utm_medium=web"><img class="embedded-publication-logo" src="https://substackcdn.com/image/fetch/$s_!KJxv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f411cce-3771-42d9-965e-1c01efe464eb_986x986.png" width="56" height="56" style="background-color: rgb(255, 255, 255);"><span class="embedded-publication-name">Product with Attitude</span><div class="embedded-publication-hero-text">AI Product Manager turning everyone into AI builders. I help you design, build and test your product, and feature it on StackShelf.app. I connect you with a supportive 10K+ community building and learning in public.</div><div class="embedded-publication-author-name">By Karo (Product with Attitude)</div></a><form class="embedded-publication-subscribe" method="GET" action="https://karozieminski.substack.com/subscribe?"><input type="hidden" name="source" value="publication-embed"><input type="hidden" name="autoSubmit" value="true"><input type="email" class="email-input" name="email" placeholder="Type your email..."><input type="submit" class="button primary" value="Subscribe"></form></div></div><p>This week I want to highlight <em><strong>Product with Attitude</strong></em> by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Karo (Product with Attitude)&quot;,&quot;id&quot;:27968736,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!aG8-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F599e664e-d6b8-4249-814a-4feadc68d706_1096x1096.png&quot;,&quot;uuid&quot;:&quot;9a794cfe-75a9-4c05-b721-aa3c2806071c&quot;}" data-component-name="MentionToDOM"></span> - a newsletter rooted in practical AI product thinking. Karo writes about how to <em>design, build, and test with clear purpose</em>, not just hype. If you want less noise and more frameworks that actually improve how you build with AI, this is one of the feeds I trust most.</p><div class="pullquote"><p>Imagine you run a restaurant with three chefs.<br>Customers keep coming in, and the waiter (your load balancer) has to assign orders.<br>In a perfect world, each chef gets an equal share.<br>But in reality? One chef is faster, another is stuck with a complicated dish, and the third just went out for coffee.</p><p>The waiter has to make quick, smart choices to keep everyone happy.</p></div><p>In a computer system, a <strong>load balancer</strong> plays the role of that attentive waiter. It&#8217;s not just blindly splitting work evenly - it&#8217;s making <em>intelligent decisions</em> about where each &#8220;<em>order</em>&#8221; (network request) should go. The goal is to keep the service running smoothly, just like our waiter keeps the restaurant flowing. This light metaphor hints at a key idea: <strong>load balancing is about intelligent flow management, not just fairness.</strong> Before diving into tech details, keep that intuitive image in mind - smart coordination to prevent overload and ensure everyone (and every server) stays productive.</p><h1>&#129513; What Load Balancing actually is</h1><p>Let&#8217;s start simple. <strong>Load balancing means distributing incoming work across multiple servers or instances</strong>.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a> Instead of one server handling all requests (and risking overload), a group of servers share the job. The goal isn&#8217;t just to &#8220;<em>spread the load</em>&#8221; evenly for fairness - it&#8217;s to ensure a few critical benefits.</p><p><strong>Performance.</strong> No single server gets overwhelmed and slow. By sharing requests, the system can respond faster. In fact, a load balancer ensures no one server bears too many requests, which directly improves application speed and responsiveness.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a></p><p><strong>Reliability (High availability).</strong> If one server fails or needs maintenance, others can take over. With a good load balancer, one node can fail without taking down the whole system. The site stays up because traffic is redirected to healthy servers (this failover mechanism is often automatic).</p><p><strong>Scalability.</strong> You can add more servers as demand grows, and the load balancer will include them in the rotation. This horizontal scaling means you can serve more users just by adding new instances, with minimal disruption.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vnez!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67f658b3-f598-4b73-9fee-ed1ce3c2047f_2395x850.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vnez!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67f658b3-f598-4b73-9fee-ed1ce3c2047f_2395x850.png 424w, https://substackcdn.com/image/fetch/$s_!vnez!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67f658b3-f598-4b73-9fee-ed1ce3c2047f_2395x850.png 848w, https://substackcdn.com/image/fetch/$s_!vnez!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67f658b3-f598-4b73-9fee-ed1ce3c2047f_2395x850.png 1272w, https://substackcdn.com/image/fetch/$s_!vnez!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67f658b3-f598-4b73-9fee-ed1ce3c2047f_2395x850.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vnez!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67f658b3-f598-4b73-9fee-ed1ce3c2047f_2395x850.png" width="1200" height="426.0989010989011" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/67f658b3-f598-4b73-9fee-ed1ce3c2047f_2395x850.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:517,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:164856,&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://iam.slys.dev/i/176401638?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67f658b3-f598-4b73-9fee-ed1ce3c2047f_2395x850.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!vnez!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67f658b3-f598-4b73-9fee-ed1ce3c2047f_2395x850.png 424w, https://substackcdn.com/image/fetch/$s_!vnez!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67f658b3-f598-4b73-9fee-ed1ce3c2047f_2395x850.png 848w, https://substackcdn.com/image/fetch/$s_!vnez!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67f658b3-f598-4b73-9fee-ed1ce3c2047f_2395x850.png 1272w, https://substackcdn.com/image/fetch/$s_!vnez!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67f658b3-f598-4b73-9fee-ed1ce3c2047f_2395x850.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 role="img" 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><title></title><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>In short, load balancing is the technique that makes a cluster of machines behave like one reliable, fast <strong>service</strong>. It&#8217;s like an orchestra conductor - they don&#8217;t play an instrument themselves, but by directing each musician at the right time, they ensure the performance (your application) is harmonious and can handle a big audience. The conductor (load balancer) doesn&#8217;t strum a violin, yet without them coordinating, the music would fall apart.</p><div class="pullquote"><p><strong>Key point:</strong> Load balancing isn&#8217;t a luxury; it&#8217;s a cornerstone of modern system design. Without it, a busy service can suffer single points of failure, slowdowns, or total crashes if one server can&#8217;t handle a spike in traffic. With it, we get a system that&#8217;s <em>steady under pressure</em> - as our restaurant story showed, it&#8217;s about managing the flow intelligently so no single chef (or server) is in the weeds.</p></div><h1>&#129504; Where Load Balancing happens &#8212; layers and levels</h1><p>Load balancing doesn&#8217;t only happen in one place or one way. It can occur at different layers of the network/application stack, each with a different scope and method.</p><div><hr></div><p><strong>Enjoying the metaphors so far? I write posts just like this - breaking down tech concepts with plain language and real-world comparisons.</strong></p><p>&#128161; Want more like this delivered to your inbox?</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><p><strong>Layer 4 (Transport layer) Load Balancing.</strong> This operates at the TCP/UDP level. A Layer 4 load balancer routes traffic based on low-level info like IP address and port, without understanding the content of the request.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a> It&#8217;s essentially doing packet forwarding. Think of it as <em>fast and dumb</em> &#8211; it just knows &#8220;<em>this packet goes to Server 1, next to Server 2</em>&#8221;, etc., and doesn&#8217;t peek inside the HTTP request. Because it&#8217;s simple, it&#8217;s very high-performance (blazingly fast). Classic network appliances and some cloud load balancers (like AWS Classic ELB or Network LB) work at L4, as do tools like HAProxy in TCP mode. An L4 balancer can&#8217;t, for example, route traffic based on an HTTP URL &#8211; it just sees addresses and ports.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a> But it&#8217;s great for raw speed and is often used for lower-level balancing of non-HTTP protocols or as a first-line balancer for lots of connections.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YrXa!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94158c12-6ff2-4739-8edc-1da24ee38d8a_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YrXa!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94158c12-6ff2-4739-8edc-1da24ee38d8a_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!YrXa!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94158c12-6ff2-4739-8edc-1da24ee38d8a_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!YrXa!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94158c12-6ff2-4739-8edc-1da24ee38d8a_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!YrXa!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94158c12-6ff2-4739-8edc-1da24ee38d8a_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YrXa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94158c12-6ff2-4739-8edc-1da24ee38d8a_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/94158c12-6ff2-4739-8edc-1da24ee38d8a_1536x1024.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;:1915308,&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://iam.slys.dev/i/176401638?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94158c12-6ff2-4739-8edc-1da24ee38d8a_1536x1024.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_!YrXa!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94158c12-6ff2-4739-8edc-1da24ee38d8a_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!YrXa!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94158c12-6ff2-4739-8edc-1da24ee38d8a_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!YrXa!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94158c12-6ff2-4739-8edc-1da24ee38d8a_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!YrXa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94158c12-6ff2-4739-8edc-1da24ee38d8a_1536x1024.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 role="img" 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><title></title><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>Layer 7 (Application layer) Load Balancing.</strong> This works at the HTTP/HTTPS (or gRPC, etc.) layer. A Layer 7 load balancer actually looks at the content of the requests &#8211; URLs, headers, cookies, etc. &#8211; and can make smarter routing decisions. For example, it could send all image requests to a dedicated image server pool, or route <code>/api/*</code> paths to a different cluster than <code>/web/*</code>. Because it operates with full knowledge of HTTP, a Layer 7 balancer can do things like TLS termination (decrypting HTTPS), cookie-based &#8220;<em>sticky sessions</em>&#8221;, and content-based routing. Nginx, Traefik, Envoy, or cloud Application Load Balancers (ALB) fall in this category. The trade-off: <strong>L7 balancing adds some overhead</strong> &#8211; it&#8217;s doing more work (maintaining two TCP connections, parsing requests) which can add a bit of latency. But in modern systems, this overhead is usually small (milliseconds or less<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a> for each request) compared to the flexibility gained. In practice, most web applications use L7 load balancing because it allows intelligent control at the HTTP level. </p><div class="pullquote"><p>In our restaurant analogy, this is like a head waiter who knows not just how many orders each chef has, but also what type of dish each order is &#8211; allowing them to assign by complexity, not just count.</p></div><p><strong>DNS Load Balancing. </strong>This is a load balancing at the <strong>DNS level</strong>, often called <em>round-robin DNS</em>. It&#8217;s actually the simplest form of load distribution. Here, multiple IP addresses are registered for one domain name. Each DNS query for the name may get a different IP from the list, thereby spreading traffic across servers geographically or by simple rotation.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-6" href="#footnote-6" target="_self">6</a> For example, <em>www.example.com</em> might resolve to <strong>IP1</strong> on one lookup and <strong>IP2</strong> on the next. Big CDNs and global services use DNS load balancing to direct users to a server cluster nearest to them. <strong>Pros:</strong> It&#8217;s simple and doesn&#8217;t require an explicit proxy in the middle. <strong>Cons:</strong> It&#8217;s very <em>coarse</em>. DNS caching can cause uneven distribution (some clients will keep hitting the same IP). And if one server goes down, DNS might still hand out its IP unless additional measures (health-check aware DNS or short TTLs) are in place. So, round-robin DNS helps with simple global load spreading, but by itself it doesn&#8217;t account for server load or even guarantee a down server is avoided. Many services combine DNS load balancing with other layers (for instance, DNS directs you to a regional load balancer, which then does L7 balancing).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2G6-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda6aa6f1-cd2d-4961-b2fb-a93077ff2856_2592x2001.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2G6-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda6aa6f1-cd2d-4961-b2fb-a93077ff2856_2592x2001.png 424w, https://substackcdn.com/image/fetch/$s_!2G6-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda6aa6f1-cd2d-4961-b2fb-a93077ff2856_2592x2001.png 848w, https://substackcdn.com/image/fetch/$s_!2G6-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda6aa6f1-cd2d-4961-b2fb-a93077ff2856_2592x2001.png 1272w, https://substackcdn.com/image/fetch/$s_!2G6-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda6aa6f1-cd2d-4961-b2fb-a93077ff2856_2592x2001.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2G6-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda6aa6f1-cd2d-4961-b2fb-a93077ff2856_2592x2001.png" width="1456" height="1124" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/da6aa6f1-cd2d-4961-b2fb-a93077ff2856_2592x2001.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1124,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:224933,&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://iam.slys.dev/i/176401638?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda6aa6f1-cd2d-4961-b2fb-a93077ff2856_2592x2001.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_!2G6-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda6aa6f1-cd2d-4961-b2fb-a93077ff2856_2592x2001.png 424w, https://substackcdn.com/image/fetch/$s_!2G6-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda6aa6f1-cd2d-4961-b2fb-a93077ff2856_2592x2001.png 848w, https://substackcdn.com/image/fetch/$s_!2G6-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda6aa6f1-cd2d-4961-b2fb-a93077ff2856_2592x2001.png 1272w, https://substackcdn.com/image/fetch/$s_!2G6-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fda6aa6f1-cd2d-4961-b2fb-a93077ff2856_2592x2001.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 role="img" 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><title></title><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>Client-Side Load Balancing.</strong> This flips the scenario: instead of a central load balancer dispatching requests, the <em>client</em> (or a client-side library) decides which server to talk to. In microservices architectures, it&#8217;s common to use <strong>service discovery</strong> where each service instance registers itself (with a service registry like Eureka, Consul, etc.). When Service A wants to call Service B, it asks the registry for all available endpoints of B. Then <em>Service A itself</em> picks one of B&#8217;s instances (often at random or round-robin) to send the request to.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-7" href="#footnote-7" target="_self">7</a> This is client-side load balancing. <strong>Advantages:</strong> It removes the extra network hop - a dedicated load balancer in between services isn&#8217;t needed, which can improve performance. Each service call goes direct to a chosen instance. <strong>Disadvantages:</strong> The logic to choose an instance now lives in the client or a library. That means complexity in each service (or language-specific libraries), and if the list of servers changes, clients need to update their info. Also, each client must implement health checking or retry logic on failures. Systems like Netflix OSS (Ribbon, Eureka) or gRPC&#8217;s built-in load balancing use this approach. <em>Think of it like removing the waiter entirely and handing each customer a list of chefs to choose from; it can work well if customers are smart about picking an available chef.</em> In practice, client-side LB is often used inside clusters (microservice-to-microservice calls), while external traffic from users is handled by centralized L7 or L4 load balancers.</p><p>To visualize a simple case of load balancing in action:</p><pre><code><code>User &#8594; Load Balancer &#8594; Servers (S1, S2, S3)</code></code></pre><p>Here, the user hits one address (the load balancer), and the balancer then forwards the request to one of the servers S1, S2, or S3. That could be happening at L4 or L7 as described. In complex systems, you might even see <em>multiple</em> layers of load balancing: e.g., DNS directs you to a region, a layer-4 balancer spreads load among data centers, and a layer-7 balancer routes within a cluster. Each layer has its role in keeping traffic flowing efficiently.</p><h1>&#9881;&#65039; Common Load Balancing strategies</h1><p>How does a load balancer actually decide where to send each request? There are many <strong>load balancing algorithms</strong> in use, each with different trade-offs. The choice can be static or dynamic. Let&#8217;s break down some real strategies and when they&#8217;re used.</p><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/DSuOB/2/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8152dd88-c88d-4f36-b020-0101be81a5a3_1220x3106.png&quot;,&quot;thumbnail_url_full&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5b0d6209-6824-4572-a8c8-eff15b1dee51_1220x3176.png&quot;,&quot;height&quot;:1021,&quot;title&quot;:&quot;Load Balancing strategies&quot;,&quot;description&quot;:&quot;&quot;}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/DSuOB/2/" width="730" height="1021" frameborder="0" scrolling="no"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><blockquote><p>&#10145;&#65039; <strong>Insight:</strong> Load balancing isn&#8217;t just about picking the next server in line. It&#8217;s about <strong>context-aware decision-making.</strong> A simple round-robin might assume every request is equal, but as we know, in reality one &#8220;<em>order</em>&#8221; might be a quick salad and another a complex entr&#233;e. Modern load balancers can be surprisingly sophisticated: some cloud load balancers use algorithms that consider things like the fewest <em>outstanding</em> requests (to account for slow vs fast requests)<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-8" href="#footnote-8" target="_self">8</a>, or combine multiple factors. The right strategy depends on your scenario &#8211; simple algorithms for simple needs, and adaptive ones when you need that extra &#8220;<em>brainpower</em>&#8221; in the balancer to keep things flowing smoothly.</p></blockquote><h1>&#127754; Load Balancing and state</h1><p>One tricky aspect in load balanced environments is <strong>user session state</strong>. Imagine a user logs into your website &#8211; their session data (e.g. login status, shopping cart) might be stored in memory on the server that handled the login. Now, what if their next request goes to a <em>different</em> server via the load balancer? That second server might not know about the user&#8217;s session, and suddenly the user appears logged out or their cart is empty. This can be a big problem if not addressed.</p><p>There are a few ways to handle state in a load-balanced system.</p><p><strong>Sticky Sessions (Session affinity).</strong> This is like telling the load balancer, &#8220;<em>once a user goes to a server, keep them on that server for all subsequent requests</em>&#8221;. The load balancer will identify the user (often via a cookie or the client&#8217;s IP) and always route them to the same backend server &#8211; effectively <strong>binding the session to that server</strong>.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-9" href="#footnote-9" target="_self">9</a> It&#8217;s like the waiter remembering you and always taking you to the same table with the same chef because that chef knows your ongoing order. Many load balancers support this: they might set a special cookie on the first response that tags the server, and read it on future requests to enforce the stickiness. <strong>Pro:</strong> It solves the immediate consistency problem &#8211; that user&#8217;s session data stays warm on one server. <strong>Cons:</strong> It can lead to uneven load (some servers get lots of &#8220;<em>sticky</em>&#8221; users, others get few) and <strong>reduces fault tolerance</strong> (if that one server crashes, those users&#8217; sessions are lost).<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-10" href="#footnote-10" target="_self">10</a> Essentially, sticky sessions trade off some of the benefits of load balancing for the sake of state. It&#8217;s often considered a quick fix or a smaller-scale solution. For example, in a pinch, you might enable sticky sessions on an AWS ELB so that users don&#8217;t bounce between instances during a short session.</p><p><strong>External Session stores.</strong> A more scalable approach is to <strong>decouple the session data from any single web server</strong>. Instead of storing session info in each server&#8217;s memory, store it in a shared place that all servers can access. This could be a database, a distributed cache like Redis or Memcached, or another dedicated session service. Then any server can handle any request because they all consult the central session store. For instance, in a PHP app, you might configure sessions to go to a Redis cluster. Or in Java, use a shared database or in-memory data grid. This way, it doesn&#8217;t matter which server the load balancer picks &#8211; the user session is the same. <strong>Pro:</strong> You regain full load balancing freedom; truly any request can go anywhere, and losing one server doesn&#8217;t drop sessions (they&#8217;re in the central store). <strong>Con:</strong> The central session store can become a new bottleneck or point of failure if not managed (though these systems are usually made robust). Also, there&#8217;s a performance cost to reading/writing session data over the network. But in practice, many large systems use this approach because it keeps the web tier stateless. In our restaurant analogy, this is like <em>writing down the order and customer preferences in a central book</em> that any chef can read &#8211; so even if the customer moves to a different table, the new chef can pick up where the last left off.</p><p><strong>Client-Side Sessions (Tokens).</strong> Another modern solution is to avoid server-held session state altogether by using something like <strong>JWTs (JSON Web Tokens)</strong> or other signed tokens. In this model, when a user logs in, the server gives the client a token (often encoded with user info and an expiration, and cryptographically signed). On subsequent requests, the client (browser/app) sends this token, and any server can validate it and know who the user is (and maybe some basic info) <em>without</em> needing to look up anything in memory or database. This is essentially a stateless session &#8211; the state is carried by the client. It&#8217;s popular in microservice and API designs. <strong>Pros:</strong> Truly stateless on the server side &#8211; any server can serve any request, no dependency on shared caches or sticky routing. <strong>Cons:</strong> You can&#8217;t easily <em>invalidate</em> a JWT (except by expiration) unless you keep a blacklist, and if you store too much in it, the token can get large. Also, for very sensitive data, you might still prefer a server-side store. Nonetheless, this approach complements load balancing by eliminating the whole issue of &#8220;<em>which server has the session</em>&#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_!ms7Y!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfd2e0d0-7502-4615-87a2-adeabfae16b5_1511x1508.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ms7Y!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfd2e0d0-7502-4615-87a2-adeabfae16b5_1511x1508.png 424w, https://substackcdn.com/image/fetch/$s_!ms7Y!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfd2e0d0-7502-4615-87a2-adeabfae16b5_1511x1508.png 848w, https://substackcdn.com/image/fetch/$s_!ms7Y!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfd2e0d0-7502-4615-87a2-adeabfae16b5_1511x1508.png 1272w, https://substackcdn.com/image/fetch/$s_!ms7Y!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfd2e0d0-7502-4615-87a2-adeabfae16b5_1511x1508.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ms7Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfd2e0d0-7502-4615-87a2-adeabfae16b5_1511x1508.png" width="1456" height="1453" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dfd2e0d0-7502-4615-87a2-adeabfae16b5_1511x1508.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1453,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:161946,&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://iam.slys.dev/i/176401638?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfd2e0d0-7502-4615-87a2-adeabfae16b5_1511x1508.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_!ms7Y!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfd2e0d0-7502-4615-87a2-adeabfae16b5_1511x1508.png 424w, https://substackcdn.com/image/fetch/$s_!ms7Y!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfd2e0d0-7502-4615-87a2-adeabfae16b5_1511x1508.png 848w, https://substackcdn.com/image/fetch/$s_!ms7Y!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfd2e0d0-7502-4615-87a2-adeabfae16b5_1511x1508.png 1272w, https://substackcdn.com/image/fetch/$s_!ms7Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfd2e0d0-7502-4615-87a2-adeabfae16b5_1511x1508.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 role="img" 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><title></title><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>Now back to <strong>sticky sessions</strong>, since that&#8217;s a direct load-balancing feature: It&#8217;s worth noting sticky sessions are often considered a <strong>necessary evil</strong> or a quick workaround. If used, one should be aware that it breaks pure load distribution. For example, if 100 users all happen to get &#8220;<em>stuck</em>&#8221; to Server A because they all hit it around the same time, Server A will carry all their load, while Server B sits idle &#8211; thus defeating the purpose of balancing. Additionally, if that server A goes down, those 100 users&#8217; sessions vanish (they were never saved elsewhere). Real-world story: an e-commerce site once had a sticky-session setup; when one server &#8220;<em>zombied</em>&#8221; (stopped actually working but didn&#8217;t fully crash), the load balancer&#8217;s health check was naive and kept sending that user&#8217;s traffic to it. Those users got a bad experience (lost carts, errors) because the LB <em>insisted</em> they go to the same dead server.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-11" href="#footnote-11" target="_self">11</a> The lesson: if you do sticky, <strong>make sure to externalize critical state</strong> or have a backup plan.</p><p><strong>Alternatives Recap:</strong> The more robust solution is to design apps to be stateless or use shared state. For instance, one can store user session data in a fast key-value store (like Redis) so that any server can retrieve it. That way, the load balancer is free to truly balance every request independently. Many frameworks have easy hooks for this (e.g., Django can use cache-based sessions, PHP can use memcached for session storage<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-12" href="#footnote-12" target="_self">12</a>, etc.). The use of JWTs or tokens has also become very common in RESTful API scenarios &#8211; it sidesteps the whole sticky session issue elegantly.</p><p>To use the analogy given: <strong>sticky sessions</strong> are like the waiter remembering <em>you specifically</em> and always seating you at the same table (helpful if your food was left there). A <strong>central session store</strong> is like the whole restaurant having a shared knowledge base (&#8220;<em>Kitchen Display System</em>&#8221;) of what each regular customer is doing &#8211; so any waiter or chef can serve you seamlessly. The latter is more scalable in a busy restaurant chain!</p><p>For beginners: the main takeaway is that load balancers by default don&#8217;t remember anything about users &#8211; which is good for stateless scaling, but you must architect your app accordingly. If you have user-specific state that can&#8217;t be lost, plan for it. Either enable session affinity on the LB (with the caveats noted) or better, keep the app stateless across servers by not tying user data to one server&#8217;s memory.</p><h1>&#128678; Load Balancing in the real world &#8212; from Nginx to Envoy</h1><p>Thus far, we&#8217;ve talked conceptually. Let&#8217;s connect this to real tools and technologies you might encounter.</p><p><strong>Traditional Software Load Balancers (L4/L7):</strong> Examples include <strong>Nginx</strong>, <strong>HAProxy</strong>, and <strong>Apache Traffic Server</strong>, among others. These are software applications you deploy on servers (or use as a service) that implement load balancing. Nginx and HAProxy are extremely popular open-source solutions. Nginx often acts as a reverse proxy and load balancer (mostly L7, but can do L4) &#8211; in fact, as of a few years ago, Nginx was estimated to handle around 25% of the traffic of the top million websites<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-13" href="#footnote-13" target="_self">13</a>, showing how widely it&#8217;s used in the wild. HAProxy is another battle-tested load balancer (the name stands for High Availability Proxy). These solutions can be deployed on commodity hardware, which historically was a big shift from the older model of <strong>hardware load balancers</strong>. A decade or two ago, companies commonly used hardware appliances (like F5 Big-IP or Citrix NetScaler) &#8211; specialized devices in data centers &#8211; to do load balancing. Now, software like Nginx/HAProxy on standard servers (or containers) does the job, which is more flexible and cost-effective.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-14" href="#footnote-14" target="_self">14</a> You can even run multiple instances for redundancy. For example, you might have two HAProxy servers in active-passive mode &#8211; if one goes down, the other takes over, to avoid the LB itself being a single point of failure.</p><p><strong>Modern Reverse Proxies and Edge Balancers:</strong> <strong>Envoy</strong> is a newer proxy developed at Lyft, now widely used, especially in cloud-native environments. Envoy supports advanced L7 features and is designed for microservices architecture. It&#8217;s often used in what&#8217;s called a <strong>service mesh</strong> (more on that in a second). <strong>Traefik</strong> is another modern L7 balancer that integrates well with container environments (like Docker/Kubernetes), auto-discovering services. These modern proxies not only do load balancing but also things like <em>circuit breaking, retries, and detailed metrics</em>. They blur the line between &#8220;<em>just a load balancer</em>&#8221; and an &#8220;<em>application traffic management layer</em>&#8221;. For example, <strong>NGINX Plus</strong> (the paid version of Nginx) and Envoy both can do adaptive health checks, content-based routing, and even act as API gateways.</p><p><strong>Service Mesh (Envoy/Istio):</strong> In cloud-native microservices, a pattern emerged: instead of each service doing client-side load balancing or having one big gateway, you can run a small &#8220;<em>sidecar</em>&#8221; proxy next to each service instance. Istio is a popular service mesh, and it uses Envoy proxies as sidecars. In an Istio service mesh, all traffic from Service A to Service B goes through Envoy, which can load balance among B&#8217;s instances, handle retries, and enforce policies. Essentially, Envoy in this context is doing client-side load balancing on behalf of the service, but it&#8217;s centrally configured. Envoy supports many algorithms (round robin, least request, etc., even &#8220;<em>ring hash</em>&#8221; for consistent hashing).<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-15" href="#footnote-15" target="_self">15</a> It also brings features like mutual TLS, traffic shadowing, etc., showing how load balancing is now part of a larger <strong>traffic control fabric</strong>. The key takeaway: tools like Envoy and Istio move load balancing into software that is deeply integrated with your application environment (Kubernetes, for example). They treat load balancing not as a separate appliance but as a built-in capability of your platform. This gives a lot of power: Istio/Envoy can, say, detect if one instance is slow and steer traffic away, or do A/B testing by routing 5% of users to a new service version. It&#8217;s beyond simple load splitting - it&#8217;s <em>intentional routing</em> as part of architecture.</p><p><strong>Cloud Provider Load Balancers:</strong> All major cloud providers offer managed load balancing services. For example, AWS has the Elastic Load Balancer (ELB) family: Classic LB, Application LB (ALB), Network LB (NLB), and newer Gateway LB. Google Cloud has Cloud Load Balancing (with global anycast capability), Azure has Azure Load Balancer and Application Gateway, etc. These services are essentially &#8220;<em>load balancers as a service</em>&#8221;. You don&#8217;t manage the software or VMs directly; the cloud handles it and usually provides high availability by default. One strong advantage is integration: e.g., an AWS ALB can integrate with auto-scaling groups and target groups so that new EC2 instances register themselves automatically. Some cloud load balancers can do things that are hard to replicate on-prem, like Google&#8217;s Cloud Load Balancing uses a <strong>single anycast IP</strong> that fronts servers in multiple regions around the world<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-16" href="#footnote-16" target="_self">16</a> - meaning a user is automatically routed to the nearest healthy instance globally, with seamless failover if an entire region goes down. Cloud LBs also often come with built-in health checks and monitoring. They might cost money per hour and per GB of data, but they save ops work.</p><p><strong>Hardware Load Balancers (Legacy and Niche):</strong> It&#8217;s worth noting that hardware load balancers are still around in some enterprises (for very high throughput needs or legacy reasons). These are physical devices with custom chips (ASICs) that can do extremely fast L4 routing, and often L7 too. They often come with features like SSL offloading at huge scale. Companies like F5 Networks dominated this space. However, the trend has been moving away from these because of cost and flexibility. Commodity servers and cloud LBs have eaten a lot of that lunch. Still, if you ever hear &#8220;<em>ADC</em>&#8221; (Application Delivery Controller), that often refers to these advanced hardware (or virtual appliance) load balancers that do a ton (load balancing, compression, security, etc.). In our analogy, this is like having a super-expensive robot waiter; it can serve really fast but might be hard to change its behavior without buying a new one.</p><p><strong>Global Traffic Managers:</strong> These are a layer above - often using DNS - to distribute traffic across geographies. For instance, if you have one deployment in US and one in Europe, a global load balancer can send European users to the EU servers and US users to US servers (reducing latency). Cloudflare, AWS Route 53 with latency-based routing, or Azure Traffic Manager serve this role. It&#8217;s load balancing at the <em>internet</em> level.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!O6Nm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb8d33dd-0e88-4cba-a487-8801ce1118d2_2586x1147.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!O6Nm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb8d33dd-0e88-4cba-a487-8801ce1118d2_2586x1147.png 424w, https://substackcdn.com/image/fetch/$s_!O6Nm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb8d33dd-0e88-4cba-a487-8801ce1118d2_2586x1147.png 848w, https://substackcdn.com/image/fetch/$s_!O6Nm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb8d33dd-0e88-4cba-a487-8801ce1118d2_2586x1147.png 1272w, https://substackcdn.com/image/fetch/$s_!O6Nm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb8d33dd-0e88-4cba-a487-8801ce1118d2_2586x1147.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!O6Nm!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb8d33dd-0e88-4cba-a487-8801ce1118d2_2586x1147.png" width="1200" height="532.4175824175824" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/db8d33dd-0e88-4cba-a487-8801ce1118d2_2586x1147.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:646,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:260247,&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://iam.slys.dev/i/176401638?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb8d33dd-0e88-4cba-a487-8801ce1118d2_2586x1147.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!O6Nm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb8d33dd-0e88-4cba-a487-8801ce1118d2_2586x1147.png 424w, https://substackcdn.com/image/fetch/$s_!O6Nm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb8d33dd-0e88-4cba-a487-8801ce1118d2_2586x1147.png 848w, https://substackcdn.com/image/fetch/$s_!O6Nm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb8d33dd-0e88-4cba-a487-8801ce1118d2_2586x1147.png 1272w, https://substackcdn.com/image/fetch/$s_!O6Nm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb8d33dd-0e88-4cba-a487-8801ce1118d2_2586x1147.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 role="img" 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><title></title><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 quick reflection on evolution: <strong>Load balancers used to be boxes in a rack</strong>, specialized and static. Now, they&#8217;re everywhere in software. In Kubernetes, every Service is like a little load balancer for pods. In front-end applications, CDNs act as load balancers for edge servers. We even have load balancing algorithms in libraries. The concept has permeated every layer because modern apps demand flexibility and resilience. Load balancing is no longer just an appliance or a single point in architecture - it&#8217;s a distributed, software-defined function that can happen at multiple points in the data flow.</p><p>To put it another way, <strong>the load balancer has become part of our &#8220;</strong><em><strong>service fabric</strong></em><strong>&#8221;.</strong> It&#8217;s not just forwarding packets; it&#8217;s often making decisions based on application behavior (URL patterns, user identity, etc.). For example, an AWS ALB can route by HTTP path to different target groups (like an internal API vs. a web front-end), essentially acting on application logic. This means as an engineer, you now think of the load balancer almost as an extension of your application - another component you configure with rules, much like you would your application code. The positive side is powerful traffic control; the downside is more complexity to manage.</p><div><hr></div><p><strong>Which tools are </strong><em><strong>you</strong></em><strong> using?</strong></p><p>Have you tried Nginx, Envoy, or maybe you&#8217;re wrestling with AWS&#8217;s ELB quirks? I&#8217;d love to hear your thoughts, questions, or stories from the trenches.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/how-load-balancing-really-works-and/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/how-load-balancing-really-works-and/comments"><span>Leave a comment</span></a></p><div><hr></div><p>In summary, <strong>open-source tools</strong> (Nginx, HAProxy, Envoy, Traefik), <strong>cloud-managed services</strong> (ELB/ALB, etc.), and <strong>software proxies in meshes</strong> are all real-world manifestations of load balancing. Often, a production system uses a combination: e.g., DNS to geo-distribute, a cloud LB at each region&#8217;s entry, and Envoy/sidecars for internal service-to-service balancing. The principles remain the same, but the implementation might be layered.</p><p>One more real-world example: <strong>Stripe</strong> (the payment company) has mentioned using L7 load balancing to route API versions and for safe deployments. Netflix famously had their Zuul (now they use Envoy) front door doing a lot of smart routing and combined that with mid-tier load balancers. These show that beyond just spreading load, companies leverage load balancers as strategic control points in the system.</p><h1>&#129518; Load Balancing and scaling</h1><p>Load balancing and horizontal <strong>scaling</strong> go hand-in-hand. If you want to scale out (add more servers to handle increased traffic), you almost always need a load balancer to distribute work to those new servers. Conversely, a load balancer without multiple servers isn&#8217;t scaling out much. They are two sides of building a scalable system:</p><ul><li><p><strong>Entry Point for Scale:</strong> The load balancer is typically the single entry point that clients talk to. Behind it, you can have N servers (where N can grow). If you get more traffic, you deploy more servers, and the load balancer starts sending traffic to those servers as well. For example, if your web service is getting 1000 requests/second on one machine at 80% CPU, you might bring up another machine. The load balancer, once it knows about the new machine, will send roughly half the traffic to each. Now each handles ~500 req/s at a comfortable 40% CPU. <strong>Crucially</strong>, from the outside, clients still just hit one address (the balancer) and don&#8217;t need to know about the change. This is how you scale transparently.</p></li><li><p><strong>Auto-Scaling Integration:</strong> In cloud environments, load balancers are tightly integrated with auto-scaling. Take AWS: you have an Auto Scaling Group (ASG) for your EC2 instances and attach it to an ALB. When the ASG launches new instances (say CPU is high, so it adds two more), those instances register with the ALB&#8217;s target group automatically. The ALB health-checks them, and as soon as they&#8217;re healthy, it starts including them in the rotation.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-17" href="#footnote-17" target="_self">17</a> Similarly, if traffic dies down and the ASG terminates instances, the load balancer stops sending traffic to those. This dynamic dance means your system can <strong>grow or shrink on demand</strong>, and the load balancer is the traffic cop that always points to the currently available servers. In Kubernetes, the equivalent is a Deployment&#8217;s pods being scaled by a Horizontal Pod Autoscaler (HPA) - the Service (which load balances to pods) notices new pods and will send traffic to them too.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-18" href="#footnote-18" target="_self">18</a> The user still hits the same Service IP or DNS name.</p></li><li><p><strong>Zero-Downtime Updates:</strong> Load balancers also help in rolling out new code or instances without downtime. For instance, you spin up new servers with a new version of your app, register them with the balancer, and deregister the old ones. If done correctly (ensuring health checks pass on new ones before removing old ones), clients won&#8217;t notice anything except maybe a slight change in response times during transitions. The LB gracefully moves traffic around. This is how <em>rolling deployments</em> or <em>blue-green deployments</em> achieve zero downtime: the load balancer switches traffic from blue to green environment.</p></li><li><p><strong>Brain Analogy:</strong> A nice way to view it: The load balancer is <em>the brain that decides where the current flows</em>. If scaling is adding more &#8220;<em>limbs</em>&#8221; or &#8220;<em>muscle</em>&#8221; to handle work, the load balancer is the nervous system routing tasks to those muscles. Without it, adding more servers wouldn&#8217;t automatically help (how would users know to go to the new server?). With it, you have a central intelligence distributing tasks so that all your capacity is utilized.</p></li></ul><p>Consider <strong>Kubernetes</strong>: by default, a Service in Kubernetes does round-robin across pod IPs (via iptables/IPVS). When HPA doubles the number of pods (say from 3 to 6 pods because CPU got high), the Service&#8217;s endpoints list updates with the new pod IPs. Instantly, the next incoming requests get spread across 6 pods instead of 3. From the client&#8217;s perspective, it&#8217;s still hitting the same service address. From the app owner&#8217;s perspective, you just scaled out seamlessly. The load balancing is what made that scaling effective, otherwise only the original 3 pods would get traffic and the other 3 sit idle.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!k8Se!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce3c610c-3ac1-4048-9084-5e25e4ec3bc2_2037x1651.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!k8Se!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce3c610c-3ac1-4048-9084-5e25e4ec3bc2_2037x1651.png 424w, https://substackcdn.com/image/fetch/$s_!k8Se!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce3c610c-3ac1-4048-9084-5e25e4ec3bc2_2037x1651.png 848w, https://substackcdn.com/image/fetch/$s_!k8Se!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce3c610c-3ac1-4048-9084-5e25e4ec3bc2_2037x1651.png 1272w, https://substackcdn.com/image/fetch/$s_!k8Se!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce3c610c-3ac1-4048-9084-5e25e4ec3bc2_2037x1651.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!k8Se!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce3c610c-3ac1-4048-9084-5e25e4ec3bc2_2037x1651.png" width="1456" height="1180" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ce3c610c-3ac1-4048-9084-5e25e4ec3bc2_2037x1651.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1180,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:254575,&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://iam.slys.dev/i/176401638?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce3c610c-3ac1-4048-9084-5e25e4ec3bc2_2037x1651.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_!k8Se!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce3c610c-3ac1-4048-9084-5e25e4ec3bc2_2037x1651.png 424w, https://substackcdn.com/image/fetch/$s_!k8Se!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce3c610c-3ac1-4048-9084-5e25e4ec3bc2_2037x1651.png 848w, https://substackcdn.com/image/fetch/$s_!k8Se!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce3c610c-3ac1-4048-9084-5e25e4ec3bc2_2037x1651.png 1272w, https://substackcdn.com/image/fetch/$s_!k8Se!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce3c610c-3ac1-4048-9084-5e25e4ec3bc2_2037x1651.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 role="img" 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><title></title><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>Similarly, on cloud VMs: without a load balancer, you might scale out by putting a new VM behind a DNS entry manually or something - a very clunky process. With a load balancer, it&#8217;s often plug-and-play: new server comes, registers, boom, it&#8217;s serving live traffic in seconds. This also aids <strong>fault tolerance</strong> - if one instance in an auto-scaled group dies unexpectedly, auto-scaling replaces it and the LB switches traffic over (plus the LB would have detected it as unhealthy and stopped sending to it within seconds or whatever health check interval).</p><p>A key term here is <strong>elasticity</strong>. Load balancers enable elasticity by serving as the abstraction layer between clients and servers. They are constantly monitoring (via health checks) and adjusting who gets traffic. Some advanced setups even let load balancers trigger scaling - e.g., if queues are building up, the LB might signal to add capacity.</p><p>In sum, <strong>scaling out = add more workers; load balancer = assign tasks to all workers</strong>. Can&#8217;t have one part without the other, if your goal is handling more load than a single machine can manage.</p><p>Finally, think about the user experience: if 100x traffic comes in (say your product goes viral), auto-scaling might bring up dozens of new instances. The users still go to one URL. Behind that URL, your load balancer fans it out to maybe 50 instances now. The alternative (without LB) would require some DNS trickery or manual traffic splitting by issuing different URLs - not practical. So load balancers <em>are the enablers of smooth scaling</em>.</p><h1>&#9888;&#65039; Pitfalls and trade-offs</h1><p>Load balancing isn&#8217;t magic - it introduces its own considerations and potential downsides. It&#8217;s important to be aware of these pitfalls.</p><p><strong>Single Point of Failure (SPOF).</strong> Ironically, the load balancer itself can become a new single point of failure. If you have one load balancer and it crashes, nobody can reach your service (even if your back-end servers are all fine). It&#8217;d be like having one waiter in the restaurant - if that waiter steps out, no orders get to any chef. <strong>Mitigation:</strong> Always have redundancy for your load balancer. This could mean running two instances in an active-passive setup (with a heartbeat and failover IP), or an active-active cluster with both sharing traffic (and clients can fail over to the surviving one). Cloud load balancers are usually designed to be redundant across zones by the provider. For on-prem, techniques like keepalived with VRRP can give two load balancer VMs a virtual IP for failover. In essence, treat your LB layer with the same high-availability approach as any critical component. Also, use health checks on the client side or DNS to detect if an LB is down and route to a backup. For example, some DNS setups will switch to an alternate IP if the primary doesn&#8217;t respond.</p><p><strong>Added Latency.</strong> Each layer of load balancing can introduce a bit of delay. For L4 it&#8217;s minimal (just another network hop). For L7, there&#8217;s the overhead of terminating TCP/SSL and processing HTTP. If you cascade load balancers (like a CDN to an L7 proxy to a service mesh sidecar), you&#8217;ve added multiple hops of processing. This <strong>latency amplification</strong> can be small individually, but it stacks up. As noted, Layer 7 gives you more control but adds latency and complexity. If misconfigured, a load balancer could also become a choke point (e.g., if it doesn&#8217;t have enough resources, it might queue requests). <strong>Mitigation:</strong> Keep the load balancer layer as slim as needed for the job. Use keep-alive connections to reduce overhead where possible. Monitor the latency your LB adds (many provide metrics for response time). In practice, a well-tuned LB adds only a few milliseconds, but it&#8217;s still overhead. Another angle: if your load balancer is geographically far from some clients, that can add latency - sometimes a DNS/global LB solution can direct users to a nearer entry point.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8Hie!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5cc773e5-390a-4683-b8aa-826b13b93bac_2048x1553.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8Hie!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5cc773e5-390a-4683-b8aa-826b13b93bac_2048x1553.png 424w, https://substackcdn.com/image/fetch/$s_!8Hie!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5cc773e5-390a-4683-b8aa-826b13b93bac_2048x1553.png 848w, https://substackcdn.com/image/fetch/$s_!8Hie!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5cc773e5-390a-4683-b8aa-826b13b93bac_2048x1553.png 1272w, https://substackcdn.com/image/fetch/$s_!8Hie!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5cc773e5-390a-4683-b8aa-826b13b93bac_2048x1553.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8Hie!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5cc773e5-390a-4683-b8aa-826b13b93bac_2048x1553.png" width="1456" height="1104" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5cc773e5-390a-4683-b8aa-826b13b93bac_2048x1553.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1104,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:225502,&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://iam.slys.dev/i/176401638?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5cc773e5-390a-4683-b8aa-826b13b93bac_2048x1553.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_!8Hie!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5cc773e5-390a-4683-b8aa-826b13b93bac_2048x1553.png 424w, https://substackcdn.com/image/fetch/$s_!8Hie!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5cc773e5-390a-4683-b8aa-826b13b93bac_2048x1553.png 848w, https://substackcdn.com/image/fetch/$s_!8Hie!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5cc773e5-390a-4683-b8aa-826b13b93bac_2048x1553.png 1272w, https://substackcdn.com/image/fetch/$s_!8Hie!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5cc773e5-390a-4683-b8aa-826b13b93bac_2048x1553.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 role="img" 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><title></title><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>Complexity and bugs.</strong> A load balancer is yet another moving piece. Misconfigurations can lead to subtle issues. For instance, choosing the wrong algorithm for your traffic pattern might cause uneven load (e.g., naive round robin when you have very long-lived connections could overload one server). Or enabling sticky sessions without realizing it (some have it default on) could undermine your scaling. Also, if you have multiple layers of LB, debugging can be hard (&#8220;<em>Is the user hitting the CDN or not? Did the mesh route this or was it the gateway?</em>&#8221;). Modern LBs have lots of features (path rewriting, header insertion, etc.) - powerful but with power comes the possibility of mistakes.</p><p><strong>Health Check Pitfalls.</strong> Health checks are how load balancers know if a server is alive and well. A common pitfall is <em>misconfigured health checks</em>. For example, a health check that only pings &#8220;<em>is port 80 open?</em>&#8221; or fetches &#8220;<em>/index.html</em>&#8221; might be too superficial. A server could be up but suffering (e.g., cannot connect to database, or in a crash-loop for certain features) and a shallow health check returns OK so the LB keeps sending traffic to it. Users hitting that server get errors, but the LB doesn&#8217;t kick it out of rotation because the health check didn&#8217;t catch the issue. <strong>Mitigation:</strong> Make health checks as robust as practical. E.g., check a simple but meaningful endpoint (like <code>/health</code> that tests connectivity to dependencies). Also set appropriate timeouts &#8211; e.g., mark a server unhealthy if it doesn&#8217;t respond within, say, 2 seconds <em>multiple</em> times, to catch hangs. We saw earlier an example: a server was out of memory and not actually processing, but still returned a basic &#8220;<em>200 OK</em>&#8221; to the LB&#8217;s trivial check, so the LB kept sending users there, essentially into a black hole. The fix was to implement deeper health checks (and alerts) to detect such failures. Another one: if health check intervals or thresholds are wrong, you might either remove servers too aggressively or keep a dead server around too long. It&#8217;s a tuning game: you want the LB to yank a bad node quickly, but also avoid flapping (e.g., a server that fails one check shouldn&#8217;t be kicked out if it was a momentary glitch).</p><p><strong>Overhead and cost.</strong> Running load balancers (especially robust ones) means you need resources for them. If self-hosting, that&#8217;s extra CPU/RAM to handle potentially tens of thousands of connections. In cloud, you often pay per hour and data - at scale, that can be significant. It&#8217;s often worth it for the benefits, but it&#8217;s a cost to account for. Also, if you encrypt traffic end-to-end, an L7 LB must decrypt and possibly re-encrypt traffic - this offloading is helpful to backend servers, but the LB itself must handle the crypto which could be CPU-heavy (though many LBs can use optimized libraries or even hardware for TLS).</p><p><strong>Layer mixing and double handling.</strong> Sometimes an application accidentally ends up with multiple load balancing decisions on the same request. For instance, DNS might send user to Region A, but that user&#8217;s request might have to go to Region B for some data, causing a trombone effect. Or if you have an L7 LB and the application then calls another service via another LB, you have to trace issues across those boundaries. Each hop is a potential failure point (DNS lookup could fail, LB could be misrouting, etc.). <strong>Observability is key</strong> - ensuring you have logs or tracing at the LB level helps.</p><p><strong>Geo-consistency and caching.</strong> In some scenarios (like caching), load balancing could reduce effectiveness if not done right. E.g., if each request of a user goes to a different cache node, they might miss out on cached results each time (cache misses). That&#8217;s why for caches or CDNs, consistent hashing or stickiness is used to improve cache hit rates by sending a user to the same node. So one must consider such trade-offs: pure load spread vs. locality.</p><p><strong>The &#8220;It&#8217;s always DNS&#8221; problem.</strong> If you rely on DNS load balancing, you might hit issues with DNS caching or TTL. Also, changes (like removing a bad server&#8217;s IP) might not propagate instantly, leading to some users still hitting a down server until their DNS cache expires. People say &#8220;<em>DNS is not a real-time load balancer</em>&#8221; for this reason. It&#8217;s best combined with other methods or with very low TTLs (which itself can increase DNS query load and sometimes be ignored by resolvers).</p><p><strong>Security Considerations.</strong> A load balancer can also be a focal point for security. If an LB is compromised or misconfigured (say, doesn&#8217;t pass along client IPs correctly, or is open to a certain attack), it can affect all traffic. Also, load balancers often terminate SSL &#8211; you need to ensure they are as secure as your app servers (patched for vulnerabilities, etc.). On the flip side, they can also help security by absorbing DDoS or hiding your internal topology.</p><p>To summarize, <strong>load balancing introduces an extra layer</strong>, and with any abstraction, you have to handle it carefully. Ensure redundancy to avoid new single points of failure, understand that it&#8217;s not set-and-forget (monitor the LB&#8217;s health and performance too), and configure things like health checks and algorithms with your app&#8217;s behavior in mind. When set up properly, a load balancer <em>greatly increases</em> reliability; if set up poorly, it can &#8220;<em>silently kill</em>&#8221; as one article put it - e.g., by routing users to a bad instance without you realizing because dashboards &#8220;<em>look green</em>&#8221;. Awareness of these pitfalls is the first step to avoiding them.</p><h1>&#128161; Load Balancing as a philosophy</h1><p>Load balancing isn&#8217;t just an engineering technique - it can be seen as a <strong>philosophy of balance</strong> that extends beyond computers. Think about it: it&#8217;s about distributing pressure intelligently so that no single component breaks, and the overall system stays healthy.</p><p>In life and in teams, the same concept applies. A good team leader is like a human load balancer: they notice when one team member is overloaded and others have capacity, and then redistribute tasks to keep the team effective (and prevent burnout). It&#8217;s about <em>balance</em>. If you give all the work to one star performer, they&#8217;ll burn out (like a server overloaded) while others stay idle (like underutilized servers). Instead, a wise leader spreads tasks according to each person&#8217;s current load and strengths&#8212;just as a load balancer routes traffic considering each server&#8217;s capacity and current usage.</p><p>We can even extend the restaurant analogy: a restaurant manager might move chefs or waiters around on a busy night to balance the workload in the kitchen and on the floor. They might notice the dessert station is backed up while the grill station is idle and shift resources accordingly. That&#8217;s load balancing in human terms.</p><p>The <strong>philosophy of load balancing</strong> is essentially <em>resilience through distribution</em>. By not putting all eggs in one basket, by not overwhelming one component, we achieve stability. This is seen in many systems: electricity grids balance load across power plants, shipping companies load balance packages across multiple routes, etc. In each case, the goal is to prevent any single point from being the bottleneck or point of failure.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6R-W!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54972c8c-9927-46d8-b434-a9bdfd3d705c_2515x1336.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6R-W!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54972c8c-9927-46d8-b434-a9bdfd3d705c_2515x1336.png 424w, https://substackcdn.com/image/fetch/$s_!6R-W!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54972c8c-9927-46d8-b434-a9bdfd3d705c_2515x1336.png 848w, https://substackcdn.com/image/fetch/$s_!6R-W!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54972c8c-9927-46d8-b434-a9bdfd3d705c_2515x1336.png 1272w, https://substackcdn.com/image/fetch/$s_!6R-W!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54972c8c-9927-46d8-b434-a9bdfd3d705c_2515x1336.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6R-W!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54972c8c-9927-46d8-b434-a9bdfd3d705c_2515x1336.png" width="1200" height="637.0879120879121" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/54972c8c-9927-46d8-b434-a9bdfd3d705c_2515x1336.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:773,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:253988,&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://iam.slys.dev/i/176401638?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54972c8c-9927-46d8-b434-a9bdfd3d705c_2515x1336.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6R-W!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54972c8c-9927-46d8-b434-a9bdfd3d705c_2515x1336.png 424w, https://substackcdn.com/image/fetch/$s_!6R-W!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54972c8c-9927-46d8-b434-a9bdfd3d705c_2515x1336.png 848w, https://substackcdn.com/image/fetch/$s_!6R-W!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54972c8c-9927-46d8-b434-a9bdfd3d705c_2515x1336.png 1272w, https://substackcdn.com/image/fetch/$s_!6R-W!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54972c8c-9927-46d8-b434-a9bdfd3d705c_2515x1336.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 role="img" 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><title></title><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>For us tech folks, maybe the poetic way to put it is: <strong>load balancers turn chaos into flow, and systems into symphonies.</strong> They take the chaos of millions of requests and orchestrate them to where they need to go, preventing cacophony (server overload or crashes). When you watch a well-balanced system under heavy load, it&#8217;s quite elegant - everything hums along, users are served, and behind the scenes dozens or thousands of machines dance in unison to handle the load.</p><p>In the end, thinking about load balancing reminds us of the importance of <em>balance in design</em>. Too often, systems fail not because they can&#8217;t handle something in general, but because one part was overstressed. By balancing, we ensure <strong>grace under pressure</strong>. It&#8217;s a mindset: anticipate where the load will be and distribute it proactively.</p><p>So, beyond just the hardware and software, load balancing teaches an almost zen lesson: don&#8217;t let any part of the system (or team) carry more than it should - spread out the work, and everything (and everyone) will last longer and perform better.</p><h1>&#9997;&#65039; Recap</h1><p><strong>Load balancing</strong> means distributing work (requests, connections) across multiple servers. It&#8217;s fundamental for building high-performance, reliable, scalable systems. Instead of one server handling everything (risking overload or downtime), you have a fleet of servers sharing the load.</p><p>It&#8217;s <em>not just about fairness</em>. The goal is <strong>resilience and efficiency</strong>. A good load balancing strategy ensures no single server becomes a bottleneck (improving throughput and response times) and that the system can tolerate failures (if one server drops, others pick up the slack). It also enables you to grow your service easily by adding more servers (horizontal scaling).</p><p>Load balancing happens at multiple layers:</p><ul><li><p><strong>L4</strong> (transport) for low-level, fast routing based on IPs/ports.</p></li><li><p><strong>L7</strong> (application) for smart routing based on HTTP content, cookies, etc., albeit with slight overhead.</p></li><li><p><strong>DNS-based</strong> for simple global distribution using multiple IPs.</p></li><li><p><strong>Client-side</strong> within apps, where services call other services directly choosing from known instances. Each layer has its use-cases, often used in combination.</p></li></ul><p>Common <strong>algorithms</strong> include Round Robin (simple rotation), Least Connections (to spread based on current load), hashing (for stickiness), weighted schemes, and more adaptive methods that account for server response times and other metrics. The choice of algorithm should match your workload (e.g., if all requests are equal, round-robin is fine; if not, consider least-connections or adaptive).</p><p><strong>State and sessions</strong> pose challenges in a distributed environment. If users bounce between servers, you must manage session data. Solutions include sticky sessions (simplest, but can undermine balancing), or better, external session stores / stateless tokens so any server can serve any user without issues. Designing stateless services as much as possible makes load balancing most effective.</p><p>In the real world, we have both <strong>open-source and commercial tools</strong>:</p><ul><li><p><em>Software like Nginx, HAProxy, Traefik, Envoy</em> are deployed by many to do L4/L7 balancing in data centers and clouds (often on standard VMs/containers, replacing the need for big hardware boxes).</p></li><li><p><em>Cloud-managed load balancers</em> (AWS ELB/ALB, Google Cloud Load Balancing, etc.) offer turnkey high availability and scalability, integrating with auto-scaling and eliminating a lot of ops overhead.</p></li><li><p><em>Service Mesh proxies</em> (Envoy via Istio/Linkerd) bring load balancing into each service instance for microservice architectures, enabling very fine-grained control and reliability techniques.<br>Historically, specialized hardware appliances were used, but today software-defined load balancers dominate due to flexibility and cost &#8211; the industry trend is moving from proprietary hardware to commodity hardware + OSS software solutions.</p></li></ul><p><strong>Auto-scaling synergy.</strong> Load balancers work hand-in-hand with scaling mechanisms. As you add instances or pods, the load balancer updates its pool and starts routing traffic to them. This allows your system to handle growth and spikes seamlessly. Without a load balancer, auto-scaling would have no coordinated way to use new instances. With it, you achieve elastic scaling &#8211; users just see a stable service, not the scaling events.</p><p><strong>Pitfalls.</strong> Be mindful of making the load balancer a new single point of failure (always have a fallback or redundancy). Recognize that each extra layer (especially L7) adds some latency and complexity, so use it judiciously. Configure health checks properly - they are your balancer&#8217;s eyes to detect bad servers, so they must actually detect real failures (deep health checks &gt; shallow ones). And monitor your load balancer like any critical component; misconfigurations there can impact the whole system (e.g., all traffic could be misrouted or throttled).</p><p>Load balancing is about turning a collection of servers into a <strong>single reliable service</strong>. It&#8217;s the reason we can build sites that serve millions of users - not on one supercomputer, but on thousands of ordinary servers working in unison. It takes what would be chaos (random, spiky traffic) and <strong>turns it into an organized flow</strong>. In doing so, it also gives us flexibility: we can maintain, deploy, and scale parts of the system without users noticing interruptions.</p><div><hr></div><p><strong>Know someone who&#8217;s just getting into backend development or cloud architecture</strong></p><p>If this post helped you, pass it along - help them level up too. &#128071;</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/leaderboard?&amp;utm_source=post&quot;,&quot;text&quot;:&quot;Refer a friend&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/leaderboard?&amp;utm_source=post"><span>Refer a friend</span></a></p><div><hr></div><p>In summary, load balancing is a foundational concept that goes beyond just splitting traffic 50/50 or 33/33/33. It&#8217;s about <strong>smart distribution of workload</strong>, with awareness of performance and reliability. When done right, it makes systems behave elegantly under load - like a well-run kitchen or a well-conducted orchestra, where no single part is overwhelmed and the output (be it dishes, music, or web pages) keeps coming smoothly. By understanding how load balancing works and its caveats, you&#8217;re better equipped to design systems that are both <strong>strong and flexible</strong>, capable of handling the rush hour of the internet without breaking a sweat.</p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p><a href="https://en.wikipedia.org/wiki/Load_balancing_(computing)">Load balancing (computing)</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p><a href="https://www.geeksforgeeks.org/system-design/what-is-load-balancer-system-design/">What is Load Balancer &amp; How Load Balancing works?</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p><a href="https://softbuilds.medium.com/load-balancers-decoded-l4-vs-l7-sticky-sessions-failovers-aa510382efae">Load Balancers Decoded: L4 vs L7, Sticky Sessions &amp; Failovers</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-4" href="#footnote-anchor-4" class="footnote-number" contenteditable="false" target="_self">4</a><div class="footnote-content"><p><a href="https://www.a10networks.com/glossary/how-do-layer-4-and-layer-7-load-balancing-differ/">How do Layer 4 Load Balancing and Layer 7 Load Balancing Differ?</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-5" href="#footnote-anchor-5" class="footnote-number" contenteditable="false" target="_self">5</a><div class="footnote-content"><p><a href="https://www.haproxy.com/blog/layer-4-vs-layer-7-load-balancing">Layer 4 vs Layer 7 Load Balancing (Differences Explained)</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-6" href="#footnote-anchor-6" class="footnote-number" contenteditable="false" target="_self">6</a><div class="footnote-content"><p><a href="https://www.cloudflare.com/learning/dns/glossary/round-robin-dns/">What is round-robin DNS?</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-7" href="#footnote-anchor-7" class="footnote-number" contenteditable="false" target="_self">7</a><div class="footnote-content"><p><a href="https://www.geeksforgeeks.org/java/client-side-service-discovery-in-microservices/">Client Side Service Discovery in Microservices</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-8" href="#footnote-anchor-8" class="footnote-number" contenteditable="false" target="_self">8</a><div class="footnote-content"><p><a href="https://medium.com/@sohail_saifi/the-load-balancer-algorithm-that-adapts-to-your-applications-behavior-44718c958685">The Load Balancer Algorithm That Adapts to Your Application&#8217;s Behavior</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-9" href="#footnote-anchor-9" class="footnote-number" contenteditable="false" target="_self">9</a><div class="footnote-content"><p><a href="https://traefik.io/glossary/what-are-sticky-sessions">What Are Sticky Sessions &#8212; How They Work and When to Use Them</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-10" href="#footnote-anchor-10" class="footnote-number" contenteditable="false" target="_self">10</a><div class="footnote-content"><p><a href="https://www.designgurus.io/answers/detail/what-are-sticky-sessions-and-when-to-avoid-them">What Are Sticky Sessions and When to Avoid Them?</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-11" href="#footnote-anchor-11" class="footnote-number" contenteditable="false" target="_self">11</a><div class="footnote-content"><p><a href="https://vishnu-g.medium.com/when-your-load-balancer-becomes-the-silent-killer-and-how-to-fix-it-cac4f69c83bd">When Your Load Balancer Becomes the Silent Killer (and How to Fix It)</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-12" href="#footnote-anchor-12" class="footnote-number" contenteditable="false" target="_self">12</a><div class="footnote-content"><p><a href="https://www.linode.com/community/questions/6459/nodebalancers-sticky-sessions-or-central-session-storage">NodeBalancers - Sticky sessions or central session storage?</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-13" href="#footnote-anchor-13" class="footnote-number" contenteditable="false" target="_self">13</a><div class="footnote-content"><p><a href="https://www.loggly.com/blog/benchmarking-5-popular-load-balancers-nginx-haproxy-envoy-traefik-and-alb/">Benchmarking 5 Popular Load Balancers: Nginx, HAProxy, Envoy, Traefik, and ALB</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-14" href="#footnote-anchor-14" class="footnote-number" contenteditable="false" target="_self">14</a><div class="footnote-content"><p><a href="https://blog.envoyproxy.io/introduction-to-modern-network-load-balancing-and-proxying-a57f6ff80236">Introduction to modern network load balancing and proxying</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-15" href="#footnote-anchor-15" class="footnote-number" contenteditable="false" target="_self">15</a><div class="footnote-content"><p><a href="https://tetrate.io/what-is-envoy-proxy">What Is Envoy Proxy and Why Do You Need It?</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-16" href="#footnote-anchor-16" class="footnote-number" contenteditable="false" target="_self">16</a><div class="footnote-content"><p><a href="https://cloudsolutions.academy/solution/what-is-anycast-ip-address-and-how-does-google-cloud-load-balancer-works/">What is Anycast IP address and how does Google Cloud Load Balancer works</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-17" href="#footnote-anchor-17" class="footnote-number" contenteditable="false" target="_self">17</a><div class="footnote-content"><p><a href="https://www.geeksforgeeks.org/devops/understanding-auto-scaling-and-load-balancing-integration-in-aws/">Understanding Auto Scaling And Load Balancing Integration In AWS</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-18" href="#footnote-anchor-18" class="footnote-number" contenteditable="false" target="_self">18</a><div class="footnote-content"><p><a href="https://medium.com/garantibbva-teknoloji/load-balancing-in-kubernetes-and-how-to-use-grpc-protocol-7735ae7faabb">Load Balancing in Kubernetes and how to use gRPC protocol</a></p><p></p></div></div>]]></content:encoded></item><item><title><![CDATA[Linear Regression — the heartbeat of Machine Learning]]></title><description><![CDATA[Machine learning fundamentals]]></description><link>https://iam.slys.dev/p/linear-regression-the-heartbeat-of</link><guid isPermaLink="false">https://iam.slys.dev/p/linear-regression-the-heartbeat-of</guid><dc:creator><![CDATA[Jakub Slys 🤖]]></dc:creator><pubDate>Mon, 23 Feb 2026 23:20:15 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!i4IZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F465a6bf7-5b95-473f-a7dd-f8e1dbf3c4c6_1536x1024.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_!i4IZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F465a6bf7-5b95-473f-a7dd-f8e1dbf3c4c6_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!i4IZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F465a6bf7-5b95-473f-a7dd-f8e1dbf3c4c6_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!i4IZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F465a6bf7-5b95-473f-a7dd-f8e1dbf3c4c6_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!i4IZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F465a6bf7-5b95-473f-a7dd-f8e1dbf3c4c6_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!i4IZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F465a6bf7-5b95-473f-a7dd-f8e1dbf3c4c6_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!i4IZ!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F465a6bf7-5b95-473f-a7dd-f8e1dbf3c4c6_1536x1024.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/465a6bf7-5b95-473f-a7dd-f8e1dbf3c4c6_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2957718,&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://iam.slys.dev/i/187834422?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F465a6bf7-5b95-473f-a7dd-f8e1dbf3c4c6_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!i4IZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F465a6bf7-5b95-473f-a7dd-f8e1dbf3c4c6_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!i4IZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F465a6bf7-5b95-473f-a7dd-f8e1dbf3c4c6_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!i4IZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F465a6bf7-5b95-473f-a7dd-f8e1dbf3c4c6_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!i4IZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F465a6bf7-5b95-473f-a7dd-f8e1dbf3c4c6_1536x1024.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 role="img" 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><title></title><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>Linear regression looks almost trivial on the surface: you draw a straight line through a cloud of points and use it to predict <code>(y)</code> from <code>(x)</code>. But that &#8220;<em>almost</em>&#8221; hides why it has survived for so long. Linear regression is the first model where you can see - clearly, concretely - the full learning loop that powers much of machine learning: propose a parameterized rule, measure its failures, and change the parameters to reduce those failures.</p><p>In other words, linear regression isn&#8217;t memorable because lines are special. It&#8217;s memorable because it&#8217;s the simplest place where <em>optimization</em> becomes a way of thinking. You&#8217;re not trying to &#8220;<em>be right</em>&#8221;. You&#8217;re trying to be <em>less wrong</em> according to a score you chose on purpose. That&#8217;s an idea you will reuse everywhere: logistic regression, matrix factorization, gradient-boosted trees, neural networks, language models. The shapes change, the data changes, the number of parameters explodes - but the heartbeat is recognizable.</p><p>This post is deliberately slow. I&#8217;m going to spend time on the emotional problem (&#8220;<em>the world is messy and I still want a simple story</em>&#8221;), then the modeling decision (&#8220;<em>a line is a constraint we choose</em>&#8221;), and only then the mechanics (&#8220;<em>how do we adjust the knobs?</em>&#8221;). When we do introduce math, we&#8217;ll treat it like a guided walkthrough, not a magic incantation. The goal is that you could sit down with a notebook and re-derive the essentials yourself - and, more importantly, that you&#8217;ll know what to look for when the line inevitably fails.</p><h2>The comforting lie of a clean relationship</h2><p>Most of us begin modeling with a quiet hope: <em>more of X means more of Y</em>. It&#8217;s a reasonable hope because it&#8217;s often directionally true. More practice tends to improve performance. More advertising tends to increase sales. More weight on a spring tends to stretch it further. These are comforting because they offer a simple story you can tell yourself and others.</p><p>Then you actually plot the data.</p><p>Instead of a neat diagonal trend, you get dots that wobble. They clump. They contradict each other. You might see points with high <code>(x)</code> and low <code>(y)</code>, and low <code>(x)</code> and high <code>(y)</code>, all in the same dataset. If you were expecting a clean relationship, the scatter plot feels like a betrayal: &#8220;<em>Was my intuition wrong? Is there no relationship at all?</em>&#8221;</p><p>This is the emotional problem linear regression solves. Not &#8220;<em>how do I find the truth</em>&#8221;, but: <strong>how do I tell a simple story about a messy world in a way that can be defended?</strong> The defensible part is crucial. Anyone can eyeball a plot and draw a line they like. But two people will draw two different lines. If your story depends on taste, you haven&#8217;t learned anything stable.</p><p>Linear regression offers a truce. It says: we will accept that points do not line up perfectly, and we will still insist on a simple summary - but we will choose that summary according to a clear rule. Not because the rule is perfect, but because it is explicit, repeatable, and critique-able. That is what turns a comforting lie into an engineering tool.</p><h2>Drawing a line is really choosing a kind of explanation</h2><p>A straight line is not &#8220;<em>the default</em>&#8221; because reality is linear. It&#8217;s the default because it is the simplest explanation that can still be wrong in a useful way. That sounds almost philosophical, but it&#8217;s practical: if you allow yourself to fit anything - curves, kinks, weird oscillations - you can always build a model that matches the data you already saw. The hard part is building something that will behave sensibly on data you haven&#8217;t seen.</p><p>A line is a bias toward simplicity. It says: &#8220;<em>I will explain the relationship using only two degrees of freedom: an overall vertical shift and a tilt</em>&#8221;. That constraint is what makes a line interpretable. You can point at it and say something like: &#8220;<em>For every additional unit of </em><code>(x)</code><em>, the predicted </em><code>(y)</code><em> changes by a constant amount</em>&#8221;. That is a statement a human can reason about.</p><p>This is a general pattern in machine learning: we choose a <em>family</em> of explanations, then search within that family. Linear regression chooses a very small family. Its strength is not that it captures everything; its strength is that it captures one kind of structure - an overall trend - while refusing to chase the noise.</p><p>And that refusal is not a moral virtue. It&#8217;s a trade-off. You give up expressive power, but you gain stability, readability, and often surprisingly strong baseline performance. If you later move to more flexible models, this early habit matters: always ask, &#8220;<em>What kind of explanations am I allowing the model to use?</em>&#8221; You don&#8217;t just fit data. You choose the vocabulary of explanations - and a line is one of the smallest vocabularies that still lets you say something meaningful.</p><h2>Before &#8220;<em>training</em>&#8221;, there is only &#8220;<em>guessing with rules</em>&#8221;</h2><p>Before we talk about training, it helps to strip away the ML vocabulary. A model is just a rule: it takes an input and returns an output. If the input is <code>(x)</code> and the output is <code>(y)</code>, then the model is a function that maps <code>(x)</code> to a prediction <code>(&#375;)</code>.</p><p>A line is a particularly simple rule with <strong>two knobs</strong>. One knob controls where the line crosses the vertical axis (the baseline when <code>(x = 0))</code>. The other knob controls how steeply the line rises or falls (how much <code>(&#375;)</code> changes when (x) changes).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!T1zh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f6c601f-b968-4a64-8472-b1430504bf38_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!T1zh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f6c601f-b968-4a64-8472-b1430504bf38_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!T1zh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f6c601f-b968-4a64-8472-b1430504bf38_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!T1zh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f6c601f-b968-4a64-8472-b1430504bf38_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!T1zh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f6c601f-b968-4a64-8472-b1430504bf38_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!T1zh!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f6c601f-b968-4a64-8472-b1430504bf38_1536x1024.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0f6c601f-b968-4a64-8472-b1430504bf38_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:3235874,&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://iam.slys.dev/i/187834422?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f6c601f-b968-4a64-8472-b1430504bf38_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!T1zh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f6c601f-b968-4a64-8472-b1430504bf38_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!T1zh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f6c601f-b968-4a64-8472-b1430504bf38_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!T1zh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f6c601f-b968-4a64-8472-b1430504bf38_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!T1zh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0f6c601f-b968-4a64-8472-b1430504bf38_1536x1024.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 role="img" 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><title></title><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>Only after you can see those knobs clearly is it useful to name them. We call the baseline the <strong>intercept</strong> and the steepness the <strong>slope</strong>. We call both knobs <strong>parameters</strong>, because they are values inside the model that we can set.</p><p>The rule is written as:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\hat{y} = b_0 + b_1 x&quot;,&quot;id&quot;:&quot;TKXCALSVIH&quot;}" data-component-name="LatexBlockToDOM"></div><p>Here <code>(b&#8320;)</code> is the intercept and <code>(b&#8321;)</code> is the slope.</p><p><strong>Worked example (making predictions).</strong></p><p>Suppose we pick <code>(b&#8320; = 1)</code> and <code>(b&#8321; = 2)</code>. Then:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\hat{y} = 1 + 2x&quot;,&quot;id&quot;:&quot;ANKPKJECRS&quot;}" data-component-name="LatexBlockToDOM"></div><p>If <code>(x = 3)</code>, substitute directly:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\hat{y} = 1 + 2\\cdot 3&quot;,&quot;id&quot;:&quot;ZMFWSPKZFW&quot;}" data-component-name="LatexBlockToDOM"></div><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\hat{y} = 1 + 6 = 7&quot;,&quot;id&quot;:&quot;REZOBZNUYH&quot;}" data-component-name="LatexBlockToDOM"></div><p>If <code>(x = 0)</code>, the prediction is just the intercept:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\hat{y} = 1 + 2\\cdot 0 = 1&quot;,&quot;id&quot;:&quot;CWAOAYAOZV&quot;}" data-component-name="LatexBlockToDOM"></div><p>Nothing mysterious is happening yet. Training will simply mean: choose <code>(b&#8320;)</code> and <code>(b&#8321;)</code> so that these predictions align well with reality.</p><h2>Noise: the reason the line will never please everyone</h2><p>Even if there is a true underlying relationship, your observed points almost never sit perfectly on a line. This is not because your data is &#8220;<em>bad</em>&#8221;. It&#8217;s because the world contains more variation than your measurement captures.</p><p>Sometimes the noise is literal measurement error: a sensor has jitter, a scale is miscalibrated, a human labeler is inconsistent, a number gets rounded. Sometimes it&#8217;s behavioral variability: two people can receive the same input and respond differently for reasons you didn&#8217;t measure. And often it&#8217;s missing variables: you&#8217;re modeling <code>(y)</code> with one feature <code>(x)</code>, but the real system depends on many factors.</p><p>A useful mental model is:</p><ul><li><p>there may be a clean trend,</p></li><li><p>but each observed point is the trend plus &#8220;<em>everything else</em>&#8221;.</p></li></ul><p>Linear regression doesn&#8217;t deny &#8220;<em>everything else</em>&#8221;. It just refuses to model it explicitly. It says: I will capture the main direction with a line, and I will treat the leftovers as noise.</p><p>That makes the phrase &#8220;<em>the line doesn&#8217;t hit all points</em>&#8221; feel normal rather than suspicious. In fact, if your line hits every point exactly, you should be cautious: either the problem is artificially clean, or you&#8217;ve accidentally let the model become too flexible (overfitting in disguise), or you&#8217;re evaluating on the same data you trained on in a way that hides generalization error.</p><p>Noise is also why humility matters in ML. If the data-generating process is noisy, then a perfect predictor might not exist even in principle. The best you can do is reduce uncertainty and make useful probabilistic or average-case predictions. Linear regression is the first model that gently forces you to accept that &#8220;<em>some error</em>&#8221; is not failure - it&#8217;s reality.</p><h2>The first key idea: error is not embarrassment, it&#8217;s feedback</h2><p>Once you accept that a line cannot satisfy every point, you need a different relationship with &#8220;<em>being wrong</em>&#8221;. In machine learning, error is not embarrassment. Error is the mechanism by which learning happens.</p><p>Take a point <code>((x&#7522;, y&#7522;))</code>. Your model predicts <code>(&#375;&#7522;)</code>. The difference between <code>(y&#7522;)</code> and <code>(&#375;&#7522;)</code> is not abstract - it is a visible vertical gap on the scatter plot. If the point lies above the line, the model predicted too low. If it lies below the line, the model predicted too high.</p><p>This matters because it turns learning into a loop:</p><ol><li><p>make a prediction using your current parameters,</p></li><li><p>compare the prediction to the truth,</p></li><li><p>use the comparison to decide how to adjust.</p></li></ol><p>Without step <code>(2)</code>, you have no guidance. You can &#8220;<em>guess</em>&#8221; different lines, but you cannot say which direction is improvement. So the core requirement for training is not cleverness; it is <strong>a consistent way to measure misses</strong>.</p><p>A subtle point: the error must be defined in a way the model can respond to smoothly. If tiny parameter changes cause unpredictable swings in the error measure, learning becomes chaotic. Linear regression with standard error definitions behaves nicely, which is another reason it&#8217;s such a good first model: the feedback is stable enough that you can build intuition about iterative improvement.</p><p>So in this section, the main idea is psychological as much as technical: errors are not shameful artifacts to hide. They are the signal that drives parameter adjustment.</p><div><hr></div><p>&#128161; <em>What if being wrong is the whole point?</em></p><p>In machine learning, mistakes aren&#8217;t something to hide - they&#8217;re the mechanism that makes improvement possible.</p><p>&#128073; <strong>Subscribe</strong> to explore more ideas where math quietly reshapes how we think.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h2>Residuals as a diagnostic, not just a number</h2><p>After you&#8217;ve stared at those vertical gaps for a while, it&#8217;s helpful to name them: they are <strong>residuals</strong>. For each point <code>(i)</code>, we define the residual as observed minus predicted:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;e_i = y_i - \\hat{y}_i&quot;,&quot;id&quot;:&quot;ADBSQLHCPW&quot;}" data-component-name="LatexBlockToDOM"></div><p>And since:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\hat{y}_i = b_0 + b_1 x_i&quot;,&quot;id&quot;:&quot;PPMRRVSFCQ&quot;}" data-component-name="LatexBlockToDOM"></div><p>we can write:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;e_i = y_i - (b_0 + b_1 x_i)&quot;,&quot;id&quot;:&quot;ARJBJQFDZI&quot;}" data-component-name="LatexBlockToDOM"></div><p>The sign matters. If <code>(e&#7522; &gt; 0)</code>, you underpredicted. If <code>(e&#7522;&lt; 0)</code>, you overpredicted.</p><p><strong>Worked example (computing residuals).</strong><br>Suppose our data points are:</p><ul><li><p><code>((1, 2))</code></p></li><li><p><code>((2, 3))</code></p></li><li><p><code>((3, 5))</code></p></li></ul><p>and our current line is:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\hat{y} = 1 + 1x&quot;,&quot;id&quot;:&quot;TNCWZCXQUI&quot;}" data-component-name="LatexBlockToDOM"></div><p>Compute predictions:</p><ul><li><p>at <code>(x = 1): (&#375; = 1 + 1 = 2)</code></p></li><li><p>at <code>(x = 2): (&#375; = 1 + 2 = 3)</code></p></li><li><p>at <code>(x = 3): (&#375; = 1 + 3 = 4)</code></p></li></ul><p>Now residuals <code>(e&#7522; = y&#7522; - &#375;&#7522;)</code>:</p><ul><li><p><code>(e&#8321; = 2 - 2 = 0)</code></p></li><li><p><code>(e&#8322; = 3 - 3 = 0)</code></p></li><li><p><code>(e&#8323; = 5 - 4 = 1)</code></p></li></ul><p>So far, residuals look &#8220;<em>fine</em>&#8221;. But the real power is diagnostic: residuals tell stories in aggregate. If residuals are mostly positive for large <code>(x)</code>, you&#8217;re systematically underpredicting in that region. If they cluster negative for small <code>(x)</code>, you&#8217;re systematically overpredicting there. Residuals aren&#8217;t just numbers - they&#8217;re a microscope for model mismatch.</p><h2>The second key idea: to optimize, you need one score to minimize</h2><p>Residuals give you many pieces of feedback - one per point. But to choose between two candidate lines, you need a single scoreboard number. Otherwise, you&#8217;re stuck arguing about trade-offs point by point: &#8220;<em>This line is better here, but worse there</em>&#8221;.</p><p>This is why loss functions exist. A <strong>loss function</strong> compresses the whole set of residuals into one number that the computer can minimize.</p><p>A common choice is mean squared error <code>(MSE)</code>. If you have <code>(n)</code> points, define:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\text{MSE} = \\frac{1}{n}\\sum e_i^2&quot;,&quot;id&quot;:&quot;LUVFRDVGEE&quot;}" data-component-name="LatexBlockToDOM"></div><p>This does two things at once. First, it makes all contributions nonnegative by squaring. Second, it makes &#8220;<em>big mistakes</em>&#8221; count more than &#8220;<em>small mistakes</em>&#8221;.</p><p><strong>Worked example (aggregating to one score).</strong></p><p>Using the residuals from the previous section <code>([0, 0, 1])</code>, compute <code>MSE</code>:</p><p>Square each residual:</p><ul><li><p><code>(0&#178; = 0)</code></p></li><li><p><code>(0&#178; = 0)</code></p></li><li><p><code>(1&#178; = 1)</code></p></li></ul><p>Sum them:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\sum e_i^2 = 0+0+1 = 1&quot;,&quot;id&quot;:&quot;RRDHFEPMFP&quot;}" data-component-name="LatexBlockToDOM"></div><p>Divide by <code>(n = 3)</code>:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\text{MSE} = \\frac{1}{3} \\approx 0.333&quot;,&quot;id&quot;:&quot;LMWRWUNXAW&quot;}" data-component-name="LatexBlockToDOM"></div><p>Now we can compare lines. A line that produces <code>MSE (0.2)</code> is &#8220;<em>better</em>&#8221; than one that produces <code>MSE (0.3)</code>, <em>under this definition of better</em>. That last clause is important: optimization doesn&#8217;t discover goodness; it operationalizes the goodness you defined.</p><h2>Why squared error feels harsh &#8212; and why that harshness is useful</h2><p>Squared error is opinionated. It says: large errors are disproportionately bad. That can feel harsh, especially if you&#8217;re thinking in human terms where a miss is a miss. But squared error is a deliberate choice about priorities.</p><p>To see the effect, compare two residual sets:</p><ul><li><p><code>Set A: ([2, 2, 2])</code></p></li><li><p><code>Set B: ([0, 0, 4])</code></p></li></ul><p>Under absolute error, both have total error (6). Squared error distinguishes them.</p><p>Compute squared sums:</p><p>For A:</p><ul><li><p><code>(2&#178; = 4)</code> three times</p></li><li><p>sum (<code>= 4 + 4 + 4 = 12</code>)</p></li></ul><p>For B:</p><ul><li><p><code>(0&#178; = 0)</code></p></li><li><p><code>(0&#178; = 0)</code></p></li><li><p><code>(4&#178; = 16)</code></p></li><li><p>sum <code>(= 16)</code></p></li></ul><p>So squared error prefers A (many small misses) over B (one big miss). That&#8217;s the harshness.</p><p>Why is that useful? Sometimes it matches reality. In many systems, a few catastrophic predictions cause outsized damage: a medical dose that&#8217;s wildly off, a delivery ETA that&#8217;s wrong by hours, a credit decision that misprices risk severely. Squared error encodes &#8220;<em>avoid disasters even if it means tolerating mild imperfection elsewhere</em>&#8221;.</p><p>There&#8217;s also a computational reason: squaring creates a smooth, bowl-shaped objective for linear regression. Smoothness means that small parameter changes lead to predictable loss changes, which makes optimization stable. If your loss surface has sharp corners, learning algorithms can jitter or stall. So squared error is not only a value judgment; it&#8217;s an engineering choice that makes the search landscape easier to navigate.</p><div><hr></div><p>&#9878;&#65039; <em>Would you rather tolerate many small misses or prevent one big failure?</em></p><p>Every loss function encodes a value judgment - even when it looks purely mathematical.</p><p>&#128172; <strong>Comment</strong> - would you design the objective differently?</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/linear-regression-the-heartbeat-of/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/linear-regression-the-heartbeat-of/comments"><span>Leave a comment</span></a></p><div><hr></div><h2>Optimization as a story of two knobs and repeated correction</h2><p>Now we return to the two knobs: intercept <code>(b&#8320;)</code> and slope <code>(b&#8321;)</code>. Optimization is the process of adjusting these knobs to reduce the loss - usually MSE.</p><p>At a human level, you can already anticipate the direction of many corrections. If your line sits too high across the plot - meaning most points fall below it - then most residuals are negative, and lowering the intercept should help. If your line is too low, raising the intercept should help.</p><p>Slope is about imbalance across <code>(x)</code>. If you underpredict at high <code>(x)</code> and overpredict at low <code>(x)</code>, your line is too flat and should tilt upward. If the opposite happens, it&#8217;s too steep and should flatten.</p><p>The key is that training is rarely a one-shot act. It&#8217;s a loop:</p><ul><li><p>pick initial <code>(b&#8320;, b&#8321;)</code>,</p></li><li><p>compute predictions <code>(&#375;&#7522;)</code>,</p></li><li><p>compute residuals <code>(e&#7522;)</code>,</p></li><li><p>compute loss,</p></li><li><p>adjust <code>(b&#8320;, b&#8321;)</code> to reduce loss,</p></li><li><p>repeat.</p></li></ul><p>This &#8220;<em>tiny edits</em>&#8221; framing matters because it generalizes. Even though linear regression can be solved directly with a closed-form formula, most modern ML training feels like this loop. Once you&#8217;re comfortable with &#8220;<em>we improve by repeated correction</em>&#8221;, later ideas - learning rates, convergence, early stopping, optimizer choices - feel like natural refinements rather than arcane rituals.</p><p>The goal isn&#8217;t to make optimization sound glamorous. It&#8217;s closer to careful woodworking: measure, shave a little, measure again. And the more clearly you can connect each shave to the measurement, the more trustworthy the process becomes.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4dTC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F671fec52-4c63-45ac-a358-d01d4fb12f5f_960x540.gif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4dTC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F671fec52-4c63-45ac-a358-d01d4fb12f5f_960x540.gif 424w, https://substackcdn.com/image/fetch/$s_!4dTC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F671fec52-4c63-45ac-a358-d01d4fb12f5f_960x540.gif 848w, https://substackcdn.com/image/fetch/$s_!4dTC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F671fec52-4c63-45ac-a358-d01d4fb12f5f_960x540.gif 1272w, https://substackcdn.com/image/fetch/$s_!4dTC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F671fec52-4c63-45ac-a358-d01d4fb12f5f_960x540.gif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4dTC!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F671fec52-4c63-45ac-a358-d01d4fb12f5f_960x540.gif" width="1200" height="675" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/671fec52-4c63-45ac-a358-d01d4fb12f5f_960x540.gif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:540,&quot;width&quot;:960,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:211682,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/gif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/187834422?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F671fec52-4c63-45ac-a358-d01d4fb12f5f_960x540.gif&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!4dTC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F671fec52-4c63-45ac-a358-d01d4fb12f5f_960x540.gif 424w, https://substackcdn.com/image/fetch/$s_!4dTC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F671fec52-4c63-45ac-a358-d01d4fb12f5f_960x540.gif 848w, https://substackcdn.com/image/fetch/$s_!4dTC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F671fec52-4c63-45ac-a358-d01d4fb12f5f_960x540.gif 1272w, https://substackcdn.com/image/fetch/$s_!4dTC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F671fec52-4c63-45ac-a358-d01d4fb12f5f_960x540.gif 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 role="img" 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><title></title><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><h2>The hill-and-valley picture: turning model fitting into navigation</h2><p>The optimization loop becomes much easier to reason about once you adopt the hill-and-valley picture.</p><p>Imagine every possible pair <code>((b&#8320;, b&#8321;))</code> as a location on a map. For each location, you can compute the loss (say, <code>MSE</code>) using your dataset. Now imagine the loss as a height. High loss is a mountain. Low loss is a valley. Training means finding the lowest valley.</p><p>This turns a vague task (&#8220;<em>fit the model</em>&#8221;) into navigation (&#8220;<em>walk downhill</em>&#8221;). It also clarifies why the loss function is so central. Without a scalar loss, you can&#8217;t define height; without height, you can&#8217;t define downhill.</p><p>For linear regression with squared error, this landscape has a particularly friendly shape: it&#8217;s a smooth bowl. Intuitively, if you start from a bad line and move a little in a helpful direction, the loss tends to decrease smoothly; you don&#8217;t hit unpredictable cliffs. That&#8217;s why the metaphor is not just motivational - it reflects a real mathematical property (convexity) that makes training reliable.</p><p>But even if you don&#8217;t use that word, the practical takeaway is simple: in this setting, there aren&#8217;t many &#8220;<em>competing explanations</em>&#8221; with similar loss. There is a single best region. So if your training is unstable, it&#8217;s often because of the step size, data scaling, or implementation - problems you can fix - rather than because the landscape itself is treacherous.</p><p>This mental picture is also a bridge to gradient descent: if you can estimate the local slope of the terrain, you can decide where to step next.</p><h2>Gradient descent: learning by taking steps you can justify</h2><p>Gradient descent can be introduced without derivatives by asking a plain question: <strong>if I nudge a knob slightly, does the loss go up or down?</strong> If nudging <code>(b&#8321;)</code> upward makes the loss smaller, you should increase <code>(b&#8321;)</code>. If it makes the loss bigger, you should decrease <code>(b&#8321;)</code>. Do the same for <code>(b&#8320;)</code>. Repeat.</p><p>Derivatives enter as the clean, efficient way to compute those &#8220;<em>nudges</em>&#8221; without trial-and-error probing. They tell you how sensitive the loss is to each parameter.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Z1ic!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff84462ec-35eb-4bcb-9379-6957373061f1_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Z1ic!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff84462ec-35eb-4bcb-9379-6957373061f1_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Z1ic!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff84462ec-35eb-4bcb-9379-6957373061f1_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Z1ic!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff84462ec-35eb-4bcb-9379-6957373061f1_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Z1ic!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff84462ec-35eb-4bcb-9379-6957373061f1_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Z1ic!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff84462ec-35eb-4bcb-9379-6957373061f1_1536x1024.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f84462ec-35eb-4bcb-9379-6957373061f1_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:3252345,&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://iam.slys.dev/i/187834422?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff84462ec-35eb-4bcb-9379-6957373061f1_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Z1ic!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff84462ec-35eb-4bcb-9379-6957373061f1_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!Z1ic!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff84462ec-35eb-4bcb-9379-6957373061f1_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!Z1ic!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff84462ec-35eb-4bcb-9379-6957373061f1_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!Z1ic!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff84462ec-35eb-4bcb-9379-6957373061f1_1536x1024.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 role="img" 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><title></title><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>Let&#8217;s derive the gradients for <code>MSE</code> step by step, carefully.</p><p>Start with:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;L = \\frac{1}{n}\\sum e_i^2&quot;,&quot;id&quot;:&quot;XDOKPKYJCM&quot;}" data-component-name="LatexBlockToDOM"></div><p>Residual is:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;e_i = y_i - \\hat{y}_i&quot;,&quot;id&quot;:&quot;GVBGYETXIP&quot;}" data-component-name="LatexBlockToDOM"></div><p>And prediction is:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\hat{y}_i = b_0 + b_1 x_i&quot;,&quot;id&quot;:&quot;GNNXHMENKZ&quot;}" data-component-name="LatexBlockToDOM"></div><p>So:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;e_i = y_i - (b_0 + b_1 x_i)&quot;,&quot;id&quot;:&quot;JYBOUDDYMX&quot;}" data-component-name="LatexBlockToDOM"></div><p>Differentiate <code>(L)</code> with respect to <code>(b&#8320;)</code>. Use the chain rule:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\frac{\\partial L}{\\partial b_0} = \\frac{1}{n}\\sum 2e_i \\frac{\\partial e_i}{\\partial b_0}&quot;,&quot;id&quot;:&quot;SXXOUBTOHS&quot;}" data-component-name="LatexBlockToDOM"></div><p>Since <code>(e&#7522; = y&#7522; - b&#8320; - b&#8321; x&#7522;)</code>,</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\frac{\\partial e_i}{\\partial b_0} = -1&quot;,&quot;id&quot;:&quot;CVKMMBMVVJ&quot;}" data-component-name="LatexBlockToDOM"></div><p>So:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\frac{\\partial L}{\\partial b_0} = -\\frac{2}{n}\\sum e_i&quot;,&quot;id&quot;:&quot;JOONBKMQGA&quot;}" data-component-name="LatexBlockToDOM"></div><p>Similarly for <code>(b&#8321;)</code>:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\frac{\\partial L}{\\partial b_1} = \\frac{1}{n}\\sum 2e_i \\frac{\\partial e_i}{\\partial b_1}&quot;,&quot;id&quot;:&quot;NSCCXRRXPB&quot;}" data-component-name="LatexBlockToDOM"></div><p>But:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\frac{\\partial e_i}{\\partial b_1} = -x_i&quot;,&quot;id&quot;:&quot;AFLAILOLDB&quot;}" data-component-name="LatexBlockToDOM"></div><p>So:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\frac{\\partial L}{\\partial b_1} = -\\frac{2}{n}\\sum e_i x_i&quot;,&quot;id&quot;:&quot;DRMDNBAETT&quot;}" data-component-name="LatexBlockToDOM"></div><p>Gradient descent updates:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;b_0 := b_0 - \\alpha \\frac{\\partial L}{\\partial b_0}&quot;,&quot;id&quot;:&quot;STCKSRFJBM&quot;}" data-component-name="LatexBlockToDOM"></div><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;b_1 := b_1 - \\alpha \\frac{\\partial L}{\\partial b_1}&quot;,&quot;id&quot;:&quot;RQLLEZRALY&quot;}" data-component-name="LatexBlockToDOM"></div><p>Here <code>(&#120572;)</code> is the learning rate: too large and you overshoot; too small and you crawl.</p><p><strong>Worked example (one gradient step).</strong><br>Data: <code>((1, 2))</code>, <code>((2, 3))</code>. Start <code>(b&#8320; = 0)</code>, <code>(b&#8321; = 0)</code>.</p><p>Predictions: <code>(&#375; = [0, 0])</code>. Residuals: <code>(e = [2, 3])</code>.</p><p>Initial <code>MSE</code>:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;L = \\frac{1}{2}(2^2+3^2)&quot;,&quot;id&quot;:&quot;JGLCEITUYJ&quot;}" data-component-name="LatexBlockToDOM"></div><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;L = \\frac{1}{2}(4+9)=6.5&quot;,&quot;id&quot;:&quot;CUQRJZGYZR&quot;}" data-component-name="LatexBlockToDOM"></div><p>Gradients:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\frac{\\partial L}{\\partial b_0} = -\\frac{2}{2}(2+3)=-5&quot;,&quot;id&quot;:&quot;CDDZRRVFEY&quot;}" data-component-name="LatexBlockToDOM"></div><p></p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\frac{\\partial L}{\\partial b_1} = -\\frac{2}{2}(2\\cdot1+3\\cdot2)= -(2+6)=-8&quot;,&quot;id&quot;:&quot;NKTPIVWIUJ&quot;}" data-component-name="LatexBlockToDOM"></div><p></p><p>Choose <code>(&#120572; = 0.1)</code>. Update:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;b_0 = 0 - 0.1(-5)=0.5&quot;,&quot;id&quot;:&quot;VPWQGOLOKU&quot;}" data-component-name="LatexBlockToDOM"></div><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;b_1 = 0 - 0.1(-8)=0.8&quot;,&quot;id&quot;:&quot;OSFKYTJFFP&quot;}" data-component-name="LatexBlockToDOM"></div><p>New predictions: at <code>(x = 1)</code>, <code>(&#375; = 1.3)</code>; at <code>(x = 2)</code>, <code>(&#375; = 2.1)</code>. Residuals: <code>(0.7, 0.9)</code>.</p><p>New <code>MSE</code>:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;L = \\frac{1}{2}(0.7^2+0.9^2)&quot;,&quot;id&quot;:&quot;FNNPDIYKPD&quot;}" data-component-name="LatexBlockToDOM"></div><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;L = \\frac{1}{2}(0.49+0.81)=0.65&quot;,&quot;id&quot;:&quot;JCITTMWRYU&quot;}" data-component-name="LatexBlockToDOM"></div><p>One justified step took loss from <code>(6.5)</code> to <code>(0.65)</code>. That&#8217;s the learning loop in miniature.</p><h2>A concrete walkthrough: hours studied vs. exam score</h2><p>Now let&#8217;s step away from arithmetic and return to the lived feel of training.</p><p>Imagine a dataset of students: hours studied <code>(x-axis)</code> and exam score <code>(y-axis)</code>. You plot it and see the usual mess. Some students studied a lot but scored poorly - sleep deprivation, stress, test anxiety, maybe they focused on the wrong topics. Some studied little but scored well - prior knowledge, strong intuition, lucky question coverage. But despite the chaos, the cloud leans upward: more studying tends to help.</p><p>Suppose your initial line is too flat. Conceptually, that means it doesn&#8217;t &#8220;<em>respect</em>&#8221; the upward lean of the data. What happens to residuals? On the right side (high study hours), the points tend to sit above your line. Those are positive residuals: you underpredicted the high-study students. On the left side (low study hours), points tend to sit below your line. Those are negative residuals: you overpredicted the low-study students.</p><p>That residual pattern is not random noise; it&#8217;s a coherent critique. It&#8217;s the dataset saying: &#8220;<em>Your slope is too small</em>&#8221;.</p><p>So the optimizer increases the slope a little. As the slope increases, the right end of the line rises (helping underpredictions on high study hours) and the left end drops relative to before (helping overpredictions on low study hours). The loss decreases.</p><p>Then you might notice something else: perhaps the line is now consistently too low overall. That would show up as many positive residuals across the board, suggesting the intercept should increase. Training becomes a repeated, almost conversational adjustment: tilt, shift, re-check. Not until it&#8217;s perfect - until further adjustments stop making meaningful improvements.</p><h2>What &#8220;<em>best fit</em>&#8221; really means: the line that makes the fairest trade-offs</h2><p>&#8220;<em>Best fit</em>&#8221; is a dangerously friendly phrase, because it sounds like the line should match as many points as possible. But in noisy data, matching many points exactly is not the goal - and often not even possible.</p><p>Under squared error, the &#8220;<em>best</em>&#8221; line is the one that minimizes <code>MSE</code>:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;\\text{MSE} = \\frac{1}{n}\\sum e_i^2&quot;,&quot;id&quot;:&quot;UQXGUMRATE&quot;}" data-component-name="LatexBlockToDOM"></div><p>That definition implies a particular kind of compromise. Every data point gets a vote, and the line positions itself to make the total squared discomfort as small as possible. It will not satisfy the outliers, and it will not satisfy every region equally. Instead, it makes trade-offs according to the rules encoded in the loss function.</p><p>This is why I sometimes describe optimization as producing a notion of &#8220;<em>fairness</em>&#8221;, but a very specific, mechanical fairness: fairness <strong>as defined by the objective</strong>. Squared error gives more influence to points with large residuals, because shrinking a large residual yields a big loss reduction. If you used absolute error, you would get a different &#8220;<em>fair</em>&#8221; compromise. If you weighted certain points more heavily (for example, high-value customers), you&#8217;d get yet another.</p><p>This framing helps you avoid a common confusion: if the fitted line doesn&#8217;t look like what you expected, it may not be &#8220;<em>wrong</em>.&#8221; It may be doing exactly what you asked under your chosen loss - especially if the dataset contains outliers, nonlinearity, or heteroskedastic noise (changing variance). &#8220;<em>Best fit</em>&#8221; is not a platonic ideal. It&#8217;s the best answer to a question you defined.</p><h2>The model&#8217;s humility: what linear regression refuses to claim</h2><p>A straight line can&#8217;t express a threshold, a curve, a plateau, or an interaction - at least not without additional feature engineering. If the real relationship is &#8220;<em>benefit increases quickly at first, then levels off</em>&#8221;, a line will insist on one constant rate of change. If the real relationship is &#8220;<em>nothing happens until </em><code>(x)</code><em> crosses a boundary</em>&#8221;, a line will smear that boundary into gradual change. If two variables interact (say, studying helps only if you also sleep enough), a single-feature linear regression can&#8217;t see that at all.</p><p>This is not a bug. It is the consequence of choosing a simple explanation on purpose.</p><p>There&#8217;s a kind of integrity in that refusal. Linear regression will not pretend to have discovered a complex mechanism. It will tell you only what fits inside its vocabulary: an overall trend plus a baseline. That&#8217;s why it remains a foundational learning tool - because it makes the boundary between &#8220;<em>what the model can say</em>&#8221; and &#8220;<em>what the world might be doing</em>&#8221; very clear.</p><p>In practice, this humility makes linear regression useful even when it&#8217;s not &#8220;<em>the best predictor</em>&#8221;. It&#8217;s often an excellent baseline and a strong diagnostic. If a complex model claims huge gains over linear regression, you can ask: is the relationship truly nonlinear, or did the complex model pick up leakage, spurious correlations, or noise? If linear regression performs surprisingly well, that&#8217;s also information: perhaps your problem is dominated by a simple trend, and you should focus on data quality, measurement, and feature design rather than architectural complexity.</p><p>Learning to appreciate what a model refuses to claim is a deep ML habit. It keeps you honest, and it keeps your systems more stable.</p><h2>When optimization can&#8217;t save you: the failure modes that look like &#8220;<em>bad training</em>&#8221;</h2><p>There are times when you can do everything &#8220;<em>right</em>&#8221; in training - correct code, stable optimization, convergence - and still feel disappointed. This is not always a training problem. Often it&#8217;s a problem of mismatch between the model family, the features, and the world.</p><p>If the true relationship is curved, no amount of optimizing a line will remove structure from the residuals. You can minimize MSE perfectly <em>within the space of lines</em> and still see a systematic pattern: residuals positive in the middle and negative at the ends, or vice versa. That pattern is a clue that your explanation vocabulary is too small.</p><p>If an important variable is missing, the model will treat its influence as noise. Imagine predicting exam score from hours studied but ignoring sleep. The model will &#8220;<em>see</em>&#8221; sleep as unexplained variability. Your residuals will be larger than they need to be, and you may falsely conclude the problem is inherently unpredictable.</p><p>Outliers are another classic failure mode, especially under squared error. Since squared error punishes large residuals heavily, a few extreme points can tug the line away from the majority. The optimizer is not misbehaving; it is faithfully minimizing the objective you gave it. If those outliers are measurement errors, this is painful. If they are legitimate rare cases, you have a real trade-off: do you want to serve the typical case well, or do you want to reduce catastrophic failures on rare points?</p><p>The practical lesson is: when results look like &#8220;<em>bad training</em>&#8221;, ask whether the model is actually failing to optimize - or whether it is optimizing something reasonable over a representation that cannot capture the structure you care about.</p><h2>Common misunderstandings: where beginners talk themselves into the wrong conclusion</h2><p>Linear regression is interpretable, which is wonderful, but it also invites overconfident storytelling.</p><p>A big one is causation. A fitted slope does not mean <code>(x)</code> causes <code>(y)</code>. It means that within your dataset, variation in <code>(x)</code> is associated with variation in <code>(y)</code>, after whatever other features you included (if any). Confounders can create impressive slopes that vanish when you measure the right variables. Correlation is not a technicality - it&#8217;s the default state of observational data.</p><p>Another misunderstanding is treating the slope as a law of nature. The slope depends on the population you sampled, the range of <code>(x)</code> values present, and the other variables you did or did not include. Add a new feature and the slope can change, not because the world changed, but because you changed what the model is allowed to attribute to each feature.</p><p>A third trap is trusting a single summary metric too much. <code>MSE</code> can look &#8220;<em>good</em>&#8221; while the model makes systematic errors in certain ranges of <code>(x)</code>, or for certain subgroups. You need residual plots and slice analysis to see whether the errors are randomly scattered (a sign you&#8217;ve captured the main structure) or patterned (a sign you&#8217;re missing something).</p><h2>Closing: the real heartbeat is &#8220;<em>define error, then minimize it</em>&#8221;</h2><p>If you zoom out far enough, linear regression stops being &#8220;<em>about lines</em>&#8221; and becomes &#8220;<em>about learning as disciplined correction</em>&#8221;.</p><p>You start with a parameterized rule - a rule with knobs. You don&#8217;t pretend it&#8217;s true. You simply commit to a vocabulary of explanations you&#8217;re willing to use. Then you define what it means to be wrong in a way that is explicit and computable. That definition becomes a single objective number. And once you have a number, you can improve the rule by changing the knobs to reduce it.</p><p>That is the heartbeat: <strong>define error, then minimize it</strong>.</p><p>Everything else - residuals, squared loss, gradients, learning rates - is structure built around that rhythm to make it reliable. Linear regression is the cleanest place to hear the beat without distractions. The moment you internalize it, later models feel less like magic. A neural network is not an alien artifact; it is the same loop with more knobs. A large language model is the same loop at enormous scale. The details matter, of course - but the mindset transfers.</p><p>There&#8217;s also a quiet reassurance in this. Machine learning can look like a zoo of architectures and acronyms. Linear regression reminds you that, underneath, we&#8217;re doing something modest and human: we propose a simple story, we listen to how it fails, and we revise the story according to a rule we can explain. If you can do that with a line, you&#8217;re already thinking the way the rest of machine learning asks you to think - even when the models stop looking like lines.</p><div><hr></div><p>&#10084;&#65039; <em>If you felt the heartbeat&#8230;</em></p><p>The mindset behind linear regression is the same one powering neural networks and language models - just scaled up.</p><p>&#128257; <strong>Share</strong> this with someone learning machine learning - it might save them years of confusion.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/linear-regression-the-heartbeat-of?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/linear-regression-the-heartbeat-of?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><ol><li><p><strong><a href="https://a.co/d/0jlbjexn">An Introduction to Statistical Learning: with Applications in Python (Springer Texts in Statistics) 2023rd Edition</a></strong> <em>by Gareth James, Daniela Witten, Trevor Hastie , Robert Tibshirani, Jonathan Taylor</em></p></li><li><p><strong><a href="https://a.co/d/0dK0vp8Y">The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition</a></strong> <em>by Trevor Hastie, Robert Tibshirani, Jerome Friedman</em></p></li><li><p><strong><a href="https://a.co/d/03Bb6pWe">All of Statistics: A Concise Course in Statistical Inference (Springer Texts in Statistics)</a></strong> <em>by Larry Wasserman</em></p></li><li><p><strong><a href="https://a.co/d/02kYNKuh">Pattern Recognition and Machine Learning (Information Science and Statistics)</a></strong></p><p><em>by Christopher M. Bishop</em></p></li><li><p><strong><a href="https://scikit-learn.org/stable/modules/linear_model.html">scikit-learn documentation (Linear Models)</a></strong></p></li><li><p><strong><a href="https://cs229.stanford.edu/main_notes.pdf">Stanford CS229 notes (linear regression + optimization)</a> </strong><em>by Andrew Ng and Tengyu Ma</em></p></li></ol>]]></content:encoded></item><item><title><![CDATA[Thinking clearly in interviews — Two Sum]]></title><description><![CDATA[Understanding the why before the code (Rust &#183; Python &#183; Scala)]]></description><link>https://iam.slys.dev/p/thinking-clearly-in-interviews-two</link><guid isPermaLink="false">https://iam.slys.dev/p/thinking-clearly-in-interviews-two</guid><dc:creator><![CDATA[Jakub Slys 🤖]]></dc:creator><pubDate>Mon, 16 Feb 2026 21:19:42 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!SkPr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60470bed-6c74-4f6e-9005-062c48e182f2_1536x1024.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_!SkPr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60470bed-6c74-4f6e-9005-062c48e182f2_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!SkPr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60470bed-6c74-4f6e-9005-062c48e182f2_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!SkPr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60470bed-6c74-4f6e-9005-062c48e182f2_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!SkPr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60470bed-6c74-4f6e-9005-062c48e182f2_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!SkPr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60470bed-6c74-4f6e-9005-062c48e182f2_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!SkPr!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60470bed-6c74-4f6e-9005-062c48e182f2_1536x1024.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/60470bed-6c74-4f6e-9005-062c48e182f2_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2253121,&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://iam.slys.dev/i/187834092?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60470bed-6c74-4f6e-9005-062c48e182f2_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!SkPr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60470bed-6c74-4f6e-9005-062c48e182f2_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!SkPr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60470bed-6c74-4f6e-9005-062c48e182f2_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!SkPr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60470bed-6c74-4f6e-9005-062c48e182f2_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!SkPr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60470bed-6c74-4f6e-9005-062c48e182f2_1536x1024.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 role="img" 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><title></title><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>&#9888;&#65039; <strong>Before we dive in &#8212; highly worth your attention</strong></p><div class="embedded-publication-wrap" data-attrs="{&quot;id&quot;:3477571,&quot;name&quot;:&quot;Lights On by Farida&quot;,&quot;logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!rtf8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0130bc80-296c-498f-8eef-8962c2088bcd_1024x1024.png&quot;,&quot;base_url&quot;:&quot;https://fafi25.substack.com&quot;,&quot;hero_text&quot;:&quot;A systems-driven newsletter from a data engineer and cybersecurity thinker, decoding complex data, technology, and business trends into actionable insight.&quot;,&quot;author_name&quot;:&quot;Farida Khalaf&quot;,&quot;show_subscribe&quot;:true,&quot;logo_bg_color&quot;:&quot;#faf5ff&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="EmbeddedPublicationToDOMWithSubscribe"><div class="embedded-publication show-subscribe"><a class="embedded-publication-link-part" native="true" href="https://fafi25.substack.com?utm_source=substack&amp;utm_campaign=publication_embed&amp;utm_medium=web"><img class="embedded-publication-logo" src="https://substackcdn.com/image/fetch/$s_!rtf8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0130bc80-296c-498f-8eef-8962c2088bcd_1024x1024.png" width="56" height="56" style="background-color: rgb(250, 245, 255);"><span class="embedded-publication-name">Lights On by Farida</span><div class="embedded-publication-hero-text">A systems-driven newsletter from a data engineer and cybersecurity thinker, decoding complex data, technology, and business trends into actionable insight.</div><div class="embedded-publication-author-name">By Farida Khalaf</div></a><form class="embedded-publication-subscribe" method="GET" action="https://fafi25.substack.com/subscribe?"><input type="hidden" name="source" value="publication-embed"><input type="hidden" name="autoSubmit" value="true"><input type="email" class="email-input" name="email" placeholder="Type your email..."><input type="submit" class="button primary" value="Subscribe"></form></div></div><p><em><strong>Lights On</strong></em> by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Farida Khalaf&quot;,&quot;id&quot;:47192869,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!nBHI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F117d97dc-0da6-4fcf-9202-f7b5e956c047_1024x1024.png&quot;,&quot;uuid&quot;:&quot;6afb7f7c-5137-4ffa-9f95-16b77d82fe6b&quot;}" data-component-name="MentionToDOM"></span> - a publication where systems thinking meets <em>real-world AI</em> and <em>business insights</em>. Farida breaks down complexity into clarity, with frameworks and perspectives that make tech trends feel actionable rather than overwhelming.</p><div><hr></div><p>You&#8217;re standing in a small market with a basket in one hand and a short list in the other. You remember you have a coupon that takes exactly a fixed amount off - say, $9 - but it only applies if you buy two items whose prices add up to that amount. Easy, you think: <strong>just glance at the tags and find a pair</strong>.</p><p>Then the mild confusion starts. There are more items than you expected. Some prices repeat. A few are even discounted in odd ways, so the same number shows up again and again. You catch yourself circling the same shelf twice, picking up an item, putting it back, and wondering if you already considered it. The problem isn&#8217;t that anything is &#8220;<em>wrong</em>&#8221; - it&#8217;s that your brain is doing a very human thing: <strong>searching without a system</strong>.</p><p>Nothing is broken here. This is what happens when the space of possibilities grows: <strong>what felt like a quick visual match turns into a process problem</strong>. And process problems are exactly what coding interviews are designed to surface - not whether you&#8217;ve seen a trick before, but whether you can turn a fuzzy search into a clean, explainable method.</p><blockquote><p><strong>Problem</strong></p><p>Given an array of integers, return indices of the two numbers such that they add up to a specific target.</p><p><strong>Examples</strong></p><p>Given <code>nums = [2, 7, 11, 15]</code>, <code>target = 9</code>, Because <code>nums[0] + nums[1] = 2 + 7 = 9</code>, return <code>[0, 1].</code></p><p><strong>Constraints</strong></p><p>You may assume that each input would have exactly one solution, and you may not use the same element twice.</p></blockquote><p>The Two Sum problem is that market moment, translated into arrays and indices. The best solutions don&#8217;t come from moving faster; they come from deciding what you&#8217;re going to remember as you scan, and how you&#8217;ll prove to yourself (and an interviewer) that you didn&#8217;t miss anything.</p><h1>&#127897;&#65039; Why is it so interesting</h1><p>From an interviewer&#8217;s perspective, Two Sum is deceptively small. The statement fits in a couple of lines, the examples look friendly, and most candidates feel they &#8220;<em>basically get it</em>&#8221; within seconds. That&#8217;s exactly why it works: it creates a situation where it&#8217;s easy to start coding before you&#8217;ve demonstrated good engineering judgment.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!MZEP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fe46a90-1ba7-4db8-9c71-e9dc02de8902_2268x1300.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MZEP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fe46a90-1ba7-4db8-9c71-e9dc02de8902_2268x1300.png 424w, https://substackcdn.com/image/fetch/$s_!MZEP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fe46a90-1ba7-4db8-9c71-e9dc02de8902_2268x1300.png 848w, https://substackcdn.com/image/fetch/$s_!MZEP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fe46a90-1ba7-4db8-9c71-e9dc02de8902_2268x1300.png 1272w, https://substackcdn.com/image/fetch/$s_!MZEP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fe46a90-1ba7-4db8-9c71-e9dc02de8902_2268x1300.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!MZEP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fe46a90-1ba7-4db8-9c71-e9dc02de8902_2268x1300.png" width="724.953125" height="415.75265066964283" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1fe46a90-1ba7-4db8-9c71-e9dc02de8902_2268x1300.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:835,&quot;width&quot;:1456,&quot;resizeWidth&quot;:724.953125,&quot;bytes&quot;:203227,&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://iam.slys.dev/i/187834092?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fe46a90-1ba7-4db8-9c71-e9dc02de8902_2268x1300.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!MZEP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fe46a90-1ba7-4db8-9c71-e9dc02de8902_2268x1300.png 424w, https://substackcdn.com/image/fetch/$s_!MZEP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fe46a90-1ba7-4db8-9c71-e9dc02de8902_2268x1300.png 848w, https://substackcdn.com/image/fetch/$s_!MZEP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fe46a90-1ba7-4db8-9c71-e9dc02de8902_2268x1300.png 1272w, https://substackcdn.com/image/fetch/$s_!MZEP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fe46a90-1ba7-4db8-9c71-e9dc02de8902_2268x1300.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 role="img" 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><title></title><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 strong interviewer isn&#8217;t looking for whether you can add two numbers. They&#8217;re watching for whether you can do a few higher-signal things under light time pressure:</p><ul><li><p><strong>You clarify what must be returned.</strong> Many candidates jump to returning the numbers themselves, not their indices. That&#8217;s not a tiny mistake; it indicates you&#8217;re not anchoring on requirements.</p></li><li><p><strong>You manage ambiguity proactively.</strong> What about duplicates? Can the same element be used twice? Is there always a solution? These questions change the shape of the code, and interviewers want to see you surface those constraints instead of stumbling into them mid-implementation.</p></li><li><p><strong>You reason about trade-offs.</strong> Two Sum has a clean naive solution and a clean optimized solution. Interviewers want to see if you can explain both, choose appropriately given constraints, and justify the complexity out loud.</p></li><li><p><strong>You implement carefully.</strong> The &#8220;<em>optimal</em>&#8221; idea is simple - a hash map lookup - but it&#8217;s also easy to get wrong with off-by-one mistakes, wrong insertion order, or duplicate handling. That&#8217;s the point: can you write correct, readable code while narrating your reasoning?</p></li></ul><p>Two Sum is also a gateway. The same mental pattern shows up everywhere: &#8220;<em>I&#8217;m scanning a list; what facts do I need to remember so I can decide quickly when I see the next element?</em>&#8221; If you can communicate that pattern well here, you&#8217;re building interview leverage for a whole family of problems.</p><h1>&#128214; Understanding the problem in plain language</h1><p>You&#8217;re given a list of integers and a target integer. You need to find <em>two different positions</em> in the list such that the values at those positions add up exactly to the target.</p><p>The output is not the values - it&#8217;s the <em>indices</em> (positions) of the two elements. The order of the returned indices usually doesn&#8217;t matter unless explicitly stated, but you should be consistent.</p><p>A few constraints matter a lot:</p><ul><li><p>There is exactly one valid answer. That means you don&#8217;t have to return all pairs, and you don&#8217;t have to deal with &#8220;<em>no solution</em>&#8221; unless the interviewer extends the problem.</p></li><li><p>You may not use the same element twice. If the target is 10 and the array contains a single 5, you can&#8217;t use that one 5 two times. But if the array contains two 5s at different indices, then you can use those two distinct elements.</p></li><li><p>Values can be negative, zero, or repeated, unless otherwise restricted. Many candidates subconsciously assume &#8220;<em>positive and distinct</em>&#8221; because the examples look that way. Don&#8217;t.</p></li></ul><p>When I restate this to a colleague, I usually say:</p><pre><code>&#8220;Scan this array and return the two positions i and j (i &#8800; j) where nums[i] + nums[j] == target.&#8221;</code></pre><p>That restatement is important because it highlights the real work: you&#8217;re not doing arithmetic, you&#8217;re doing <em>search</em>, and you&#8217;re doing it while preserving original positions.</p><h1>&#128099; Reasoning through examples</h1><p>Let&#8217;s walk slowly through the classic example:</p><ul><li><p><code>nums = [2, 7, 11, 15]</code></p></li><li><p><code>target = 9</code></p></li></ul><p>A good candidate narrates something like:</p><blockquote><p>&#8220;<em>I need two indices. If I pick 2 at index 0, I need 7 to reach 9. Is 7 present later? Yes - index 1. So the answer is [0, 1].</em>&#8221;</p></blockquote><p>That&#8217;s correct, but the interviewer wants more than correctness on the toy input. They want to hear a process that scales.</p><p>Here&#8217;s the more interview-useful narration:</p><blockquote><p>&#8220;<em>As I scan left to right, for each number x I can compute its complement </em><code>c = target - x</code><em>. If I&#8217;ve already seen c earlier, then I&#8217;ve found the pair: the earlier index of c and the current index. If not, I store x with its index for future lookups.&#8221;</em></p></blockquote><p>Now you&#8217;ve described an algorithm, not just an observation.</p><p>Let&#8217;s test the narration on something slightly trickier:</p><ul><li><p><code>nums = [3, 3]</code></p></li><li><p><code>target = 6</code></p></li></ul><p>If you store the first 3 at index 0, then when you see the second 3 at index 1, the complement is also 3, which you&#8217;ve seen. You return [0, 1]. This example is important because it proves you understand &#8220;<em>not the same element twice</em>&#8221; really means &#8220;<em>not the same index twice</em>&#8221;.</p><p>Another example that reveals common misunderstandings:</p><ul><li><p><code>nums = [1, 5, 1, 5]</code></p></li><li><p><code>target = 6</code></p></li></ul><p>There are many value matches, but the problem guarantees exactly one solution in the test setup. Still, your code should behave sensibly with duplicates. If you use a hash map of value &#8594; index, you have to decide: do you store the first index, the last index, or does it matter? It can matter if the complement equals the current value (like 3 and 3), or if the &#8220;<em>one solution</em>&#8221; guarantee is removed as a follow-up.</p><p>The key is: your reasoning needs to explicitly connect &#8220;<em>what I store</em>&#8221; with &#8220;<em>what I will look up later</em>&#8221;, and that connection should remain correct even when values repeat.</p><h1>&#128207; Constraints and what they tell us</h1><p>Interview constraints are often understated, but Two Sum is one of those problems where constraints quietly dictate the right approach.</p><p>If the array length n is small (say, a few hundred), an <code>O(n&#178;)</code> solution is perfectly fine in production and fine in many interviews. But interviews rarely choose Two Sum for <code>n=200</code>. They choose it because they want to see whether you recognize that <code>O(n&#178;)</code> becomes painful when n is large - tens of thousands, hundreds of thousands, or more.</p><p>The &#8220;<em>exactly one solution</em>&#8221; constraint is also a hint. It tells you:</p><ul><li><p>You can return as soon as you find a valid pair.</p></li><li><p>You don&#8217;t need to keep searching for alternatives.</p></li><li><p>You don&#8217;t need to worry about tie-breaking.</p></li></ul><p>The &#8220;<em>may not use the same element twice</em>&#8221; constraint is a bigger hint than it looks. It forces you to think about timing:</p><ul><li><p>If you build a map of all values first and then search, you must be careful not to pair an element with itself unless there are duplicates.</p></li><li><p>If you scan left-to-right and only allow matches with previously seen values, you automatically avoid using the same index twice. That&#8217;s a very clean correctness argument, and interviewers like correctness arguments that are easy to say out loud.</p></li></ul><p>Finally, the fact that you must return indices (not values) tells you you can&#8217;t sort the array without extra work, because sorting destroys original positions. You <em>can</em> sort if you carry indices along, but that&#8217;s already a signal: &#8220;<em>I&#8217;m choosing a more complex approach than necessary</em>&#8221;.</p><p>Constraints are the interviewer quietly telling you what kind of thinking they want to see: time complexity awareness, careful handling of duplicates, and a solution that preserves index identity.</p><h1>&#129300; The obvious first idea &#8212; and why it&#8217;s not enough</h1><p>The most natural approach is brute force:</p><ul><li><p>For each index <code>i</code></p></li><li><p>For each index <code>j &gt; i</code></p></li><li><p>Check if <code>nums[i] + nums[j] == target</code></p></li><li><p>If yes, return <code>[i, j]</code></p></li></ul><p>This is the algorithm your brain does in the market when you keep re-checking shelves: <em>try a choice, then try to match it with every other choice</em>.</p><p>Why it feels good:</p><ul><li><p>It&#8217;s simple.</p></li><li><p>It&#8217;s hard to get wrong.</p></li><li><p>It doesn&#8217;t require any extra data structure.</p></li><li><p>The code is short and readable.</p></li></ul><p>Why it&#8217;s not enough (in many interviews):</p><p>Time complexity is <code>O(n&#178;)</code>. If <code>n = 100,000</code>, that&#8217;s ~5 billion pairs in the worst case. Even if each check is fast, that&#8217;s not going to finish in a reasonable time.</p><p>More subtly, brute force doesn&#8217;t demonstrate the interview skill this problem is testing: the ability to reduce search using memory. An interviewer might accept brute force as a starting point, but they&#8217;re hoping you&#8217;ll quickly move to something better and explain <em>why</em> it&#8217;s better.</p><p>In a live setting, a strong move is:</p><ul><li><p>State the brute force approach clearly.</p></li><li><p>Give its complexity.</p></li><li><p>Then say, calmly: &#8220;<em>We can do better by trading space for time</em>.&#8221;</p></li></ul><p>That last sentence is the hinge. It signals you understand that performance improvements usually come from changing what you remember, not from writing clever arithmetic.</p><h1>&#128161; The key insight</h1><p>Two Sum becomes easy when you stop thinking of it as &#8220;<em>find two numbers</em>&#8221; and start thinking of it as:</p><blockquote><p>&#8220;<em>As I scan, what information would make the next decision instant?</em>&#8221;</p></blockquote><p>Suppose you&#8217;re currently at value <code>x</code>. You want to know if there exists a previous value <code>y</code> such that <code>y + x == target</code>. Rearranged:</p><p><code>y == target - x</code></p><p>So the decision at x reduces to a question you can answer instantly <em>if</em> you have the right memory:</p><blockquote><p><em>&#8220;Have I seen (</em><code>target - x</code><em>) before? If yes, where?&#8221;</em></p></blockquote><p>That suggests a hash map (dictionary) keyed by value, storing the index where you saw it.</p><p>The insight has two important parts:</p><ul><li><p><strong>Complement thinking:</strong> Every element defines exactly what it needs from the past (the complement).</p></li><li><p><strong>One-pass memory:</strong> If you store what you&#8217;ve seen so far, you can decide in <code>O(1)</code> average time per element.</p></li></ul><p>This is not about memorizing that &#8220;<em>Two Sum uses a hash map</em>&#8221;. It&#8217;s about noticing a pattern: <em>you don&#8217;t need to search all pairs if you can transform the question into membership queries against a set of prior observations.</em></p><p>In interviews, it&#8217;s worth saying explicitly:</p><blockquote><p><em>&#8220;I&#8217;m going to scan left to right. For each element, I&#8217;ll check whether its complement is already in the map. If it is, I return immediately. Otherwise I insert the current element with its index.&#8221;</em></p></blockquote><p>That&#8217;s the moment the interviewer relaxes a bit - because now they can evaluate execution, not direction.</p><div><hr></div><h3>&#128161; Did this mental shift click for you?</h3><p>What was your &#8220;<em>aha</em>&#8221; moment while reading this?</p><p>&#128172; Leave a comment - I&#8217;d love to know how you think about Two Sum.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/thinking-clearly-in-interviews-two/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/thinking-clearly-in-interviews-two/comments"><span>Leave a comment</span></a></p><div><hr></div><h1>&#9881;&#65039;The final approach</h1><p>Narratively, here&#8217;s the algorithm:</p><p>You keep a dictionary <code>seen</code> that maps a number value to the index where you saw it.</p><p>Then for each index <code>i</code> and value <code>x = nums[i]</code>:</p><ul><li><p>Compute <code>c = target - x</code></p></li><li><p>If <code>c</code> is in <code>seen</code>, you found the answer: <code>[seen[c], i]</code></p></li><li><p>Otherwise store <code>seen[x] = i</code> and continue</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qkO2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fa2e952-f284-4fd3-978f-57fd1dd7c7a7_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qkO2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fa2e952-f284-4fd3-978f-57fd1dd7c7a7_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!qkO2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fa2e952-f284-4fd3-978f-57fd1dd7c7a7_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!qkO2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fa2e952-f284-4fd3-978f-57fd1dd7c7a7_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!qkO2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fa2e952-f284-4fd3-978f-57fd1dd7c7a7_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qkO2!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fa2e952-f284-4fd3-978f-57fd1dd7c7a7_1536x1024.png" width="1200" height="800.2747252747253" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1fa2e952-f284-4fd3-978f-57fd1dd7c7a7_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:1497899,&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://iam.slys.dev/i/187834092?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fa2e952-f284-4fd3-978f-57fd1dd7c7a7_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!qkO2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fa2e952-f284-4fd3-978f-57fd1dd7c7a7_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!qkO2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fa2e952-f284-4fd3-978f-57fd1dd7c7a7_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!qkO2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fa2e952-f284-4fd3-978f-57fd1dd7c7a7_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!qkO2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fa2e952-f284-4fd3-978f-57fd1dd7c7a7_1536x1024.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 role="img" 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><title></title><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>Correctness, in words you can say live:</p><ul><li><p>If the answer uses indices <code>(p, q)</code> with <code>p &lt; q</code>, then when we reach q in the scan, we have already inserted <code>nums[p]</code> into <code>seen</code>.</p></li><li><p>At q, we compute complement target - <code>nums[q]</code>, which equals nums[p], so the lookup succeeds and we return <code>(p, q)</code>.</p></li><li><p>We never use the same element twice because we only match the current index with a strictly earlier index from the map.</p></li></ul><p>Edge behavior:</p><ul><li><p>Duplicates are naturally handled because values can appear multiple times; when the second instance appears, it can match the first if needed.</p></li><li><p>The only nuance is whether you store the first occurrence or overwrite with the last. With the &#8220;<em>exactly one solution</em>&#8221; guarantee, either often works, but storing the first occurrence makes the behavior more stable when duplicates exist and the guarantee is removed.</p></li></ul><p>A small but important implementation detail:</p><p>Check for the complement <strong>before</strong> inserting the current value. That ordering prevents pairing an element with itself when <code>x == target - x</code>. For example, target 6 and x 3: you want to match with a <em>previous</em> 3, not the one you&#8217;re currently at.</p><p>That check-then-insert rhythm is the cleanest version to explain and defend.</p><h1>&#9201;&#65039; Performance under interview constraints</h1><p>Time complexity:</p><ul><li><p>You do a single pass through n elements.</p></li><li><p>Each pass does a hash lookup and possibly an insert.</p></li><li><p>On average, those are <code>O(1)</code>, so total is <code>O(n)</code> average time.</p></li></ul><p>Space complexity:</p><ul><li><p>In the worst case you store each element in the map: <code>O(n)</code> space.</p></li></ul><p>In an interview, you don&#8217;t need to over-lawyer the hash table details, but you should be able to say one sentence acknowledging reality:</p><blockquote><p><em>&#8220;This is </em><code>O(n)</code><em> average time using a hash map; worst-case hash behavior exists in theory, but in practice and in typical interview models we treat it as constant-time expected operations.&#8221;</em></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_!2Me6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcaba3f1-a1ab-43aa-b714-cd472f0c8f51_1746x798.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2Me6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcaba3f1-a1ab-43aa-b714-cd472f0c8f51_1746x798.png 424w, https://substackcdn.com/image/fetch/$s_!2Me6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcaba3f1-a1ab-43aa-b714-cd472f0c8f51_1746x798.png 848w, https://substackcdn.com/image/fetch/$s_!2Me6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcaba3f1-a1ab-43aa-b714-cd472f0c8f51_1746x798.png 1272w, https://substackcdn.com/image/fetch/$s_!2Me6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcaba3f1-a1ab-43aa-b714-cd472f0c8f51_1746x798.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2Me6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcaba3f1-a1ab-43aa-b714-cd472f0c8f51_1746x798.png" width="1456" height="665" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bcaba3f1-a1ab-43aa-b714-cd472f0c8f51_1746x798.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:665,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:106695,&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://iam.slys.dev/i/187834092?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcaba3f1-a1ab-43aa-b714-cd472f0c8f51_1746x798.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_!2Me6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcaba3f1-a1ab-43aa-b714-cd472f0c8f51_1746x798.png 424w, https://substackcdn.com/image/fetch/$s_!2Me6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcaba3f1-a1ab-43aa-b714-cd472f0c8f51_1746x798.png 848w, https://substackcdn.com/image/fetch/$s_!2Me6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcaba3f1-a1ab-43aa-b714-cd472f0c8f51_1746x798.png 1272w, https://substackcdn.com/image/fetch/$s_!2Me6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbcaba3f1-a1ab-43aa-b714-cd472f0c8f51_1746x798.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 role="img" 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><title></title><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>Trade-offs you can mention calmly:</p><ul><li><p>If memory is constrained, you might consider sorting with indices (O(n log n) time, <code>O(n)</code> space for the index pairs) and using two pointers, but it&#8217;s more code and more ways to slip.</p></li><li><p>If you need all pairs (a common follow-up), the map approach needs adjustment because &#8220;<em>return immediately</em>&#8221; is no longer correct, and duplicates must be counted carefully.</p></li></ul><p>The point is not to recite complexities. The point is to show you can connect code structure to performance with confidence.</p><h1>&#128187; Implementation</h1><p>Implementation is secondary to clarity of thought - but in interviews, &#8220;<em>secondary</em>&#8221; still means &#8220;<em>must be correct</em>&#8221;.</p><p>Two Sum is a great place to practice readable implementation under time pressure:</p><ul><li><p>Use descriptive names (<code>seen</code>, <code>complement</code>).</p></li><li><p>Keep control flow linear.</p></li><li><p>Return early when you find the pair.</p></li><li><p>Make the &#8220;<em>check then insert</em>&#8221; ordering explicit.</p></li></ul><p>Below are reference implementations in <strong>Python</strong>, <strong>Rust</strong>, and <strong>Scala</strong>. Each is written in a style that&#8217;s easy to explain while typing.</p><h2>&#128013; Python implementation</h2><p>Python makes the core idea very direct: <em>a dictionary from value to index</em>.</p><pre><code>from typing import List

def two_sum(nums: List[int], target: int) -&gt; List[int]:
    # Maps value -&gt; index where it was seen
    seen = {}

    for i, x in enumerate(nums):
        complement = target - x
        if complement in seen:
            return [seen[complement], i]

        # Store AFTER checking, to avoid using the same element twice
        seen[x] = i

    # With the usual constraint &#8220;exactly one solution&#8221;, we never reach here.
    raise ValueError(&#8221;No valid pair found&#8221;)</code></pre><p>What to explain out loud while coding:</p><ul><li><p>&#8220;<code>seen</code><em> stores numbers we&#8217;ve already passed, along with their indices.</em>&#8221;</p></li><li><p>&#8220;<em>At each number x, I compute the complement and see if it&#8217;s already in </em><code>seen</code><em>.</em>&#8221;</p></li><li><p>&#8220;<em>If yes, return the earlier index and the current index.</em>&#8221;</p></li><li><p>&#8220;<em>Then I insert x for future elements.</em>&#8221;</p></li></ul><p>Common Python nuance:</p><p>If the interviewer asks about duplicates, you can say: &#8220;<em>This stores the latest index for each value because we overwrite. With the &#8216;exactly one solution&#8217; guarantee it&#8217;s fine; if we wanted the earliest index consistently, we could only insert when the value is not already present.</em>&#8221;</p><p>If you want that &#8220;<em>earliest index</em>&#8221; behavior, it&#8217;s a one-line change:</p><pre><code>if x not in seen:
    seen[x] = i</code></pre><p>But don&#8217;t add it unless you need it - extra branching is extra surface area for mistakes.</p><h2>&#129408; Rust implementation</h2><p>Rust is where candidates often get tangled - not because the algorithm changes, but because they start thinking about ownership before they&#8217;ve stabilized the control flow.</p><p>The trick is to keep it simple:</p><ul><li><p>Use <code>std::collections::HashMap&lt;i32, usize&gt;</code></p></li><li><p>Iterate with <code>enumerate()</code></p></li><li><p>Look up by reference (<code>get(&amp;complement)</code>)</p></li><li><p>Return indices as <code>Vec&lt;usize&gt;</code> or <code>Option&lt;(usize, usize)&gt;</code></p></li></ul><p>Here&#8217;s a clean version that returns a pair as <code>Option&lt;(usize, usize)&gt;</code>:</p><pre><code>use std::collections::HashMap;

pub fn two_sum(nums: &amp;[i32], target: i32) -&gt; Option&lt;(usize, usize)&gt; {
    let mut seen: HashMap&lt;i32, usize&gt; = HashMap::new();

    for (i, &amp;x) in nums.iter().enumerate() {
        let complement = target - x;

        if let Some(&amp;j) = seen.get(&amp;complement) {
            return Some((j, i));
        }

        // Insert after checking to avoid using the same index twice
        seen.insert(x, i);
    }

    None
}</code></pre><p>What&#8217;s worth calling out in Rust:</p><ul><li><p><code>nums.iter().enumerate()</code> gives <code>(usize, &amp;i32)</code>. We pattern-match <code>&amp;x</code> to copy the i32 out (cheap and simple).</p></li><li><p><code>seen.get(&amp;complement)</code> returns <code>Option&lt;&amp;usize&gt;</code>. We match <code>Some(&amp;j)</code> to copy the index out.</p></li><li><p>We insert with <code>seen.insert(x, i)</code> after the check.</p></li></ul><p>If you&#8217;re asked to match a typical &#8220;<em>always exactly one solution</em>&#8221; signature, you can unwrap (or panic) at the end, but I prefer returning <code>Option</code> because it keeps the function honest:</p><pre><code>pub fn two_sum_strict(nums: &amp;[i32], target: i32) -&gt; (usize, usize) {
    two_sum(nums, target).expect(&#8221;Exactly one solution was assumed&#8221;)
}</code></pre><p>Interviewers generally like when you separate &#8220;<em>core algorithm</em>&#8221; from &#8220;<em>assumptions about input</em>&#8221;, because it signals clean engineering instincts.</p><h2>&#128995; Scala implementation</h2><p>Scala gives you a couple of choices: immutable maps (rebuilding each time) or a mutable map (most interview-friendly here). For a one-pass <code>O(n)</code> scan, a mutable <code>HashMap</code> is straightforward.</p><pre><code>import scala.collection.mutable

object TwoSum {
  def twoSum(nums: Array[Int], target: Int): Array[Int] = {
    val seen = mutable.HashMap[Int, Int]()  // value -&gt; index

    for (i &lt;- nums.indices) {
      val x = nums(i)
      val complement = target - x

      seen.get(complement) match {
        case Some(j) =&gt; return Array(j, i)
        case None    =&gt; seen.update(x, i)
      }
    }

    // Under the usual constraint &#8220;exactly one solution&#8221;, this won&#8217;t happen.
    throw new IllegalArgumentException(&#8221;No valid pair found&#8221;)
  }
}</code></pre><p>Scala design notes you can mention:</p><ul><li><p><code>nums.indices</code> is a clean way to iterate indices without manual bounds.</p></li><li><p><code>seen.get(complement)</code> returns an <code>Option[Int]</code>, which we pattern match.</p></li><li><p><code>return</code> is used here intentionally for early exit. In purely functional Scala you might avoid <code>return</code>, but in interviews clarity beats purity - especially for a simple search with an early success condition.</p></li></ul><p>If your interviewer prefers expression-oriented style, you can still keep it readable, but don&#8217;t contort yourself. Two Sum is not the place to prove you can write clever Scala.</p><h1>&#9888;&#65039; Common interview mistakes</h1><p>Two Sum is famous, which means interviewers have seen every possible self-inflicted wound. The good news is that most mistakes are predictable.</p><p>A very common mistake is returning the values, not the indices. This usually happens when the candidate starts coding before restating the problem. The fix is procedural: always say &#8220;<em>indices</em>&#8221; out loud before you type your function signature.</p><p>Another common mistake is using the same element twice by inserting before checking. The buggy pattern looks like:</p><ul><li><p>insert <code>x</code> at index <code>i</code></p></li><li><p>check whether complement exists (it will - because you just inserted x)</p></li><li><p>accidentally return <code>(i, i)</code> when <code>x * 2 == target</code></p></li></ul><p>This is why &#8220;<em>check then insert</em>&#8221; is not just a detail - it&#8217;s a correctness guarantee you can explain in one sentence.</p><p>Duplicates cause another class of bugs. Candidates sometimes store a value &#8594; index map built from the whole array first, then do a second pass. That can work, but it forces you to handle the &#8220;<em>don&#8217;t use same index</em>&#8221; rule explicitly:</p><ul><li><p>If complement equals x, you must ensure the stored index is not i.</p></li><li><p>If there are duplicates, you might overwrite the index you actually need.</p></li></ul><p>That two-pass approach isn&#8217;t wrong, but it&#8217;s more complicated to reason about live, which makes it a riskier interview choice.</p><p>Finally, some candidates overcomplicate by sorting and using two pointers. That solution can be made correct by sorting <code>(value, originalIndex)</code> pairs, but it&#8217;s longer, easier to get wrong, and harder to narrate under time pressure. Unless the interviewer explicitly removes the hash map option (rare), sorting is usually not your best first move.</p><p>The meta-lesson: in interviews, prefer solutions that are easy to <em>defend</em>, not just easy to code.</p><div><hr></div><h3>&#9888;&#65039; Know someone preparing for interviews?</h3><p>Send this to them - it might save them from an avoidable mistake.</p><p>&#128257; Share this post with a friend grinding interview prep.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/thinking-clearly-in-interviews-two?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/thinking-clearly-in-interviews-two?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h1>&#128269; Edge cases interviewers love to ask about</h1><p>Once you produce the <code>O(n) </code>hash map solution, interviewers often probe whether you understand what makes it correct by twisting the input slightly.</p><p><strong>Duplicates where the pair uses the same value twice:</strong></p><ul><li><p><code>nums = [3, 3]</code>, <code>target = 6</code></p></li><li><p>Correct output must reference two different indices.</p></li></ul><p>If your code inserts before checking, you&#8217;ll fail here. If you check first, you&#8217;ll succeed.</p><p><strong>Negative numbers and zero:</strong></p><ul><li><p><code>nums = [-1, -2, -3, -4, -5]</code>, <code>target = -8</code> &#8594; indices for -3 and -5</p></li><li><p><code>nums = [0, 4, 3, 0]</code>, <code>target = 0</code> &#8594; indices for the two zeros</p></li></ul><p>This probes whether you accidentally assume positivity or uniqueness.</p><p><strong>Very large arrays:</strong></p><p>This is less about correctness and more about whether you can justify complexity. Interviewers want to hear: &#8220;<code>O(n)</code><em> time, </em><code>O(n)</code><em> space</em>&#8221; without hesitation, and they want you to connect the dots: &#8220;<em>We store at most one entry per element</em>&#8221;.</p><p><strong>&#8220;</strong><em><strong>What if there is no solution?</strong></em><strong>&#8221;:</strong></p><p>Even though the prompt says there is exactly one, interviewers often ask this to see if you can design a robust API. In Python you might raise an exception; in Rust you might return <code>Option</code>; in Scala you might return <code>Option[Array[Int]]</code> or throw. The key is to separate: &#8220;<em>Given the constraint, we can assume success</em>&#8221; from &#8220;<em>In production, I&#8217;d encode the possibility of failure</em>&#8221;.</p><p><strong>&#8220;</strong><em><strong>What if there are multiple solutions?</strong></em><strong>&#8221;:</strong></p><p>Now your early return behavior is no longer correct if the task is &#8220;<em>return all pairs</em>&#8221;. You&#8217;d need to collect results, and duplicates become tricky (you might need counts rather than indices, or a different approach entirely). The right response is calm: &#8220;<em>The current algorithm returns the first pair it finds; if you need all pairs, the requirements change and we need to redesign</em>&#8221;.</p><p>Edge cases aren&#8217;t a trap; they&#8217;re a conversation about whether you understand why your approach works.</p><h1>&#127891; What this problem trains you to do</h1><p>Two Sum trains a skill that matters far more than this one question: turning pairwise search into single-pass decision-making.</p><p>The reusable mental model is:</p><ul><li><p>I&#8217;m scanning items in order.</p></li><li><p>At each item, I can compute what I wish I had seen earlier.</p></li><li><p>If I record what I&#8217;ve seen in a structure optimized for membership tests, I can avoid nested loops.</p></li></ul><p>That model reappears in many forms:</p><ul><li><p>Variants like &#8220;<em>find a pair with difference k</em>&#8221; (same complement idea).</p></li><li><p>&#8220;<em>Three sum</em>&#8221; style problems (where you often fix one element and reduce to Two Sum).</p></li><li><p>Subarray sum problems (prefix sums + hash maps are the same &#8220;<em>remember what matters</em>&#8221; move).</p></li><li><p>Any streaming scenario where you can&#8217;t afford to revisit all prior data.</p></li></ul><p>But the deeper interview takeaway is communication discipline:</p><ul><li><p>Restate requirements precisely.</p></li><li><p>Name the naive solution and its cost.</p></li><li><p>Introduce the key insight as a trade: space for time.</p></li><li><p>Keep the implementation aligned with the correctness story (&#8220;<em>check then insert</em>&#8221;).</p></li></ul><p>If you can do that smoothly on Two Sum, you&#8217;re not just solving a problem - you&#8217;re demonstrating the exact style of thinking interviewers trust.</p><h1>&#127793; Closing thoughts</h1><p>Two Sum looks simple, which is why it&#8217;s such a good interview mirror. It reflects whether you can slow down just enough to be precise, then speed up with a method that stays correct when the input stops being friendly.</p><p>When you practice, don&#8217;t time yourself on typing. Time yourself on clarity: can you explain, in plain language, what you&#8217;re storing, why you&#8217;re storing it, and why that guarantees you won&#8217;t miss the answer? If you can, the code almost writes itself - and when it doesn&#8217;t, you&#8217;ll know exactly which invariant you&#8217;re trying to preserve.</p><div><hr></div><h3>&#129504; If you want to build real interview intuition&#8230;</h3><p>I write deep, calm breakdowns of classic problems - without tricks or memorization.</p><p>&#128236; Subscribe to get the next one directly.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/subscribe?"><span>Subscribe now</span></a></p>]]></content:encoded></item><item><title><![CDATA[How systems find each other — Service Discovery without magic]]></title><description><![CDATA[System design fundamentals]]></description><link>https://iam.slys.dev/p/how-systems-find-each-other-service</link><guid isPermaLink="false">https://iam.slys.dev/p/how-systems-find-each-other-service</guid><dc:creator><![CDATA[Jakub Slys 🤖]]></dc:creator><pubDate>Tue, 10 Feb 2026 21:27:22 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!2Yfy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72ebec7c-c077-4278-b53c-e56d13f34387_1536x1024.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_!2Yfy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72ebec7c-c077-4278-b53c-e56d13f34387_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2Yfy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72ebec7c-c077-4278-b53c-e56d13f34387_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!2Yfy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72ebec7c-c077-4278-b53c-e56d13f34387_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!2Yfy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72ebec7c-c077-4278-b53c-e56d13f34387_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!2Yfy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72ebec7c-c077-4278-b53c-e56d13f34387_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2Yfy!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72ebec7c-c077-4278-b53c-e56d13f34387_1536x1024.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/72ebec7c-c077-4278-b53c-e56d13f34387_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2486259,&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://iam.slys.dev/i/176729744?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72ebec7c-c077-4278-b53c-e56d13f34387_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!2Yfy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72ebec7c-c077-4278-b53c-e56d13f34387_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!2Yfy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72ebec7c-c077-4278-b53c-e56d13f34387_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!2Yfy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72ebec7c-c077-4278-b53c-e56d13f34387_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!2Yfy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72ebec7c-c077-4278-b53c-e56d13f34387_1536x1024.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 role="img" 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><title></title><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="pullquote"><p>Imagine throwing a party - fifty guests, all arriving at different times.<br>Some leave early, others show up late. The address changes mid-party.<br>Yet somehow, everyone still finds the right house.</p><p>That&#8217;s the miracle of <strong>Service Discovery</strong> - systems finding each other in a world that&#8217;s constantly moving.</p></div><p>In a distributed system, finding the &#8220;<em>right house</em>&#8221; is an everyday challenge. Services are like party guests constantly coming and going. Addresses change (containers restart, servers autoscale, IPs reassign) but somehow everything <em>still works</em>. How? The answer is <strong>service discovery</strong>. In essence, service discovery is what keeps order in chaos, ensuring that even when locations are fluid, the connections between services remain solid. In the following sections, we&#8217;ll demystify service discovery, showing that it&#8217;s not magic at all - just smart engineering that lets services continuously find each other in a changing world.</p><h1>&#129513; The problem &#8212; nothing stays still in Distributed Systems</h1><p>In a traditional monolithic application, every function call or component interaction happens <strong>inside one process</strong> or on one machine. Locating another part of the system is straightforward because everything lives together. There&#8217;s no question about &#8220;<em>where</em>&#8221; a component is - it&#8217;s in the same binary or server, so calling it is as simple as a function call.</p><div><hr></div><p><strong>Enjoying the metaphors so far? I write posts just like this - breaking down tech concepts with plain language and real-world comparisons.</strong></p><p>&#128161; Want more like this delivered to your inbox?</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><p>In <strong>microservices</strong> (and other distributed architectures), nothing stays still. Services are split out across many processes or containers, often across many hosts. These service instances <strong>come and go dynamically</strong>. Auto-scaling might spin up new instances on the fly; new deployments replace old versions; if something crashes, it might be restarted elsewhere. In cloud environments, even the network identifiers are ephemeral - containers or VMs often get random IP addresses assigned at start, which can change next time they run.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a> The number of instances isn&#8217;t fixed either; it can change based on load or schedule.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!TJS_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94437e09-91a6-4875-8923-aad9d19459e6_2263x1708.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!TJS_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94437e09-91a6-4875-8923-aad9d19459e6_2263x1708.png 424w, https://substackcdn.com/image/fetch/$s_!TJS_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94437e09-91a6-4875-8923-aad9d19459e6_2263x1708.png 848w, https://substackcdn.com/image/fetch/$s_!TJS_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94437e09-91a6-4875-8923-aad9d19459e6_2263x1708.png 1272w, https://substackcdn.com/image/fetch/$s_!TJS_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94437e09-91a6-4875-8923-aad9d19459e6_2263x1708.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!TJS_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94437e09-91a6-4875-8923-aad9d19459e6_2263x1708.png" width="1456" height="1099" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/94437e09-91a6-4875-8923-aad9d19459e6_2263x1708.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1099,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:195679,&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://iam.slys.dev/i/176729744?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94437e09-91a6-4875-8923-aad9d19459e6_2263x1708.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_!TJS_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94437e09-91a6-4875-8923-aad9d19459e6_2263x1708.png 424w, https://substackcdn.com/image/fetch/$s_!TJS_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94437e09-91a6-4875-8923-aad9d19459e6_2263x1708.png 848w, https://substackcdn.com/image/fetch/$s_!TJS_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94437e09-91a6-4875-8923-aad9d19459e6_2263x1708.png 1272w, https://substackcdn.com/image/fetch/$s_!TJS_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94437e09-91a6-4875-8923-aad9d19459e6_2263x1708.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 role="img" 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><title></title><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>Now, if you&#8217;re a service that needs to call another service, you can&#8217;t rely on a hard-coded IP or hostname, because that might be outdated the moment it&#8217;s deployed. Hardcoding addresses in config is brittle and practically impossible to maintain in a microservices ecosystem.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a> Imagine trying to keep track of 50 party guests whose addresses keep changing - that&#8217;s what it&#8217;s like in a dynamic system. The pain point is clear: in distributed systems, <em>location is fluid</em>. What was &#8220;<em>here</em>&#8221; yesterday might be gone or moved today.</p><div class="pullquote"><p><strong>Insight:</strong> Service Discovery exists because <strong>addresses are temporary - but relationships are permanent.</strong> The <em>identity</em> of the service (like &#8220;<em>User Service</em>&#8221; or &#8220;<em>Order Service</em>&#8221;) remains, even though its location keeps changing. We need a way to call &#8220;<em>User Service</em>&#8221; without caring about its current address. In other words, find the <em>who</em> no matter <em>where</em> it is now.</p></div><h1>&#9881;&#65039; What is Service Discovery (really)?</h1><p>Let&#8217;s define it in simple terms. <strong>Service Discovery</strong> is how systems <em>dynamically</em> find and connect to each other on a network. Instead of calling a service at a fixed, known address, a service will ask a central system: &#8220;<em>Where is the <strong>User Service</strong> today?</em>&#8221; - and get back the current location (IP and port, for example) of an instance of that service. This means the caller doesn&#8217;t need to know in advance where the target service lives; it only needs to know the target&#8217;s <em>name</em> or identity, and the discovery mechanism provides the real address at runtime.</p><p>At its core, service discovery is a level of indirection that separates <strong>who</strong> you want to talk to from <strong>where</strong> they are right now. You request by a logical service name or key, and the discovery system returns the actual endpoint. This is analogous to how we use a phone&#8217;s contact list: you don&#8217;t remember the exact phone number (which might change), you just tap on &#8220;<em>Mom</em>&#8221; or &#8220;<em>Alice&#8217;s Pizza</em>&#8221; and the phone figures out the current number to dial. The number could change behind the scenes (new SIM card, updated contact info), but you don&#8217;t care - you just want to reach <em>Mom</em>. Similarly, a service just wants to reach &#8220;<em>User-Service</em>&#8221; without hardcoding its address.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Gt0J!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29972993-9cd7-4a32-b262-ccccd0d38f34_2605x1822.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Gt0J!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29972993-9cd7-4a32-b262-ccccd0d38f34_2605x1822.png 424w, https://substackcdn.com/image/fetch/$s_!Gt0J!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29972993-9cd7-4a32-b262-ccccd0d38f34_2605x1822.png 848w, https://substackcdn.com/image/fetch/$s_!Gt0J!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29972993-9cd7-4a32-b262-ccccd0d38f34_2605x1822.png 1272w, https://substackcdn.com/image/fetch/$s_!Gt0J!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29972993-9cd7-4a32-b262-ccccd0d38f34_2605x1822.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Gt0J!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29972993-9cd7-4a32-b262-ccccd0d38f34_2605x1822.png" width="1200" height="839.010989010989" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/29972993-9cd7-4a32-b262-ccccd0d38f34_2605x1822.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1018,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:409868,&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://iam.slys.dev/i/176729744?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29972993-9cd7-4a32-b262-ccccd0d38f34_2605x1822.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Gt0J!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29972993-9cd7-4a32-b262-ccccd0d38f34_2605x1822.png 424w, https://substackcdn.com/image/fetch/$s_!Gt0J!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29972993-9cd7-4a32-b262-ccccd0d38f34_2605x1822.png 848w, https://substackcdn.com/image/fetch/$s_!Gt0J!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29972993-9cd7-4a32-b262-ccccd0d38f34_2605x1822.png 1272w, https://substackcdn.com/image/fetch/$s_!Gt0J!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29972993-9cd7-4a32-b262-ccccd0d38f34_2605x1822.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 role="img" 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><title></title><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>To illustrate, consider a real example from a microservice framework: in a Spring Cloud/Eureka setup, one service can simply use the <strong>logical name</strong> of another. For instance, an authentication service might call <code>&#8220;USER-SERVICE&#8221;</code> (the name) instead of a URL; Eureka will resolve that name to an actual host:port at call time.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a> The developer writes code against a service <em>name</em>, and service discovery takes care of mapping it to the current address. This makes the system <strong>flexible</strong> - services can be redeployed, moved, scaled, or replaced, and as long as they register themselves under the same name, other services can still find them.</p><p>In short, <strong>service discovery</strong> is the automated &#8220;<em>phonebook</em>&#8221; of distributed systems. It answers the ever-important question: <em>&#8220;Where is service X right now?&#8221;</em> and it answers it reliably even as the answer keeps changing over time.</p><h1>&#129504; The two flavors &#8212; Client-Side vs. Server-Side Discovery</h1><p>There are two primary models of how service discovery is implemented: <strong>client-side discovery</strong> and <strong>server-side discovery</strong>. Both achieve the same goal (routing a request to an available service instance), but they split responsibilities differently between the service client and the network infrastructure.</p><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/AI11b/1/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/74d4ea74-4042-4cdc-a360-94959602609d_1220x708.png&quot;,&quot;thumbnail_url_full&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/22f7a4f4-d107-443f-a13d-994eca84c01f_1220x778.png&quot;,&quot;height&quot;:267,&quot;title&quot;:&quot;Client-Side vs. Server-Side Discovery&quot;,&quot;description&quot;:&quot;&quot;}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/AI11b/1/" width="730" height="267" frameborder="0" scrolling="no"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><p>In <strong>client-side discovery</strong>, the client is &#8220;<em>smart</em>&#8221;. It knows about the service registry. For example, a microservice might use a discovery library (such as Netflix Ribbon with Eureka or a Consul client) to ask the registry for all live instances of &#8220;<em>User Service</em>&#8221;, then apply some load balancing algorithm (random, round-robin, etc.) to choose one instance and send the request directly to it. The client contains the discovery logic. The upside is there&#8217;s no extra network hop &#8211; the client talks straight to the target. The downside is every client must implement the discovery mechanism and keep the registry up-to-date (which typically means pulling updates or subscribing to changes).</p><p>In <strong>server-side discovery</strong>, the client is simpler &#8211; it just knows to send requests to a fixed address (for example, a load balancer URL or a proxy) and that component will do the discovery. The logic lives on the server-side component (like a reverse proxy, API gateway, or dedicated load balancer). When a request comes in, the load balancer looks up where to send it - essentially performing the discovery lookup on behalf of the client - and then forwards (proxies) the request to one of the service instances. AWS Elastic Load Balancer (ELB) works this way: your service client just calls &#8220;<em>http://my-service.loadbalancer.aws</em>&#8221; and ELB ensures it routes to one of the actual servers behind it. Kubernetes <strong>Services</strong> (the built-in kind) also behave like a server-side discovery mechanism: each Service gets a stable IP or DNS name, and behind that facade Kubernetes will direct traffic to one of the pods that currently implement that service.</p><pre><code><code>Client-side:   Client &#8594; (Service Registry lookup) &#8594; Directly to Target Service  
Server-side:  Client &#8594; (Load Balancer/Proxy) &#8594; Target Service (after LB does lookup)</code></code></pre><p>The diagram above shows the difference in call flow. In summary:</p><ul><li><p><em>Client-side discovery</em> makes the <strong>client</strong> responsible for figuring out service locations. The client must query the registry and decide <em>which</em> instance to use. This requires a bit more sophistication in each client service, but avoids an extra network hop. Many open-source systems like Netflix Eureka or HashiCorp Consul operate in this mode, often with client libraries that applications include to integrate with the registry.</p></li><li><p><em>Server-side discovery</em> offloads that work to a dedicated component (often part of the infrastructure). The client just hits a fixed endpoint and <strong>the network &#8220;</strong><em><strong>smartly</strong></em><strong>&#8221; routes</strong> the call to a service instance. This is convenient for clients (they just call a static address), but introduces an extra component that must scale and stay available. Examples include cloud load balancers (AWS ELB, Nginx or HAProxy with service discovery plugins) and Kubernetes&#8217;s internal service VIPs or service mesh proxies.</p></li></ul><pre><code><code>Client-side:   Client &#8594; (Service Registry lookup) &#8594; Directly to Target Service  </code></code></pre><p><em>Client-side service discovery.</em> The diagram above illustrates client-side discovery: the client first queries a <strong>service registry</strong> to get the current list of server instances for a given service. Then the client picks one of those instances (often using a load-balancing strategy) and sends the request directly to that instance. In this model, the client is aware of the discovery system. Netflix&#8217;s <strong>Eureka</strong> is a classic example supporting client-side discovery - applications use a Eureka client to ask the registry for service addresses. Similarly, HashiCorp <strong>Consul</strong> can be used client-side via DNS or HTTP APIs: the application itself looks up the service&#8217;s address and connects to it.</p><pre><code><code>Server-side:  Client &#8594; (Load Balancer/Proxy) &#8594; Target Service (after LB does lookup)</code></code></pre><p><em>Server-side service discovery.</em> The diagram above shows server-side discovery: the client sends its request to a fixed <strong>load balancer (or proxy)</strong> address. The load balancer (acting as a smart router) then consults the service registry or its own mapping of healthy instances and forwards the request to one of the service instances. The client doesn&#8217;t need to know anything about the service registry or where instances are - it just knows the address of the load balancer. <strong>Kubernetes</strong> implements this pattern with its Service abstraction (and kube-proxy), giving each service a stable IP/hostname and distributing incoming requests to available pods. Traditional hardware or software load balancers (like F5, Nginx, HAProxy) can also do service discovery by periodically polling a registry or receiving updates, so they always know where to route traffic.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dplQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F329cb989-7de6-4887-a3c5-ecbcc0867491_1590x1445.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dplQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F329cb989-7de6-4887-a3c5-ecbcc0867491_1590x1445.png 424w, https://substackcdn.com/image/fetch/$s_!dplQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F329cb989-7de6-4887-a3c5-ecbcc0867491_1590x1445.png 848w, https://substackcdn.com/image/fetch/$s_!dplQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F329cb989-7de6-4887-a3c5-ecbcc0867491_1590x1445.png 1272w, https://substackcdn.com/image/fetch/$s_!dplQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F329cb989-7de6-4887-a3c5-ecbcc0867491_1590x1445.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dplQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F329cb989-7de6-4887-a3c5-ecbcc0867491_1590x1445.png" width="1456" height="1323" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/329cb989-7de6-4887-a3c5-ecbcc0867491_1590x1445.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1323,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:153867,&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://iam.slys.dev/i/176729744?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F329cb989-7de6-4887-a3c5-ecbcc0867491_1590x1445.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_!dplQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F329cb989-7de6-4887-a3c5-ecbcc0867491_1590x1445.png 424w, https://substackcdn.com/image/fetch/$s_!dplQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F329cb989-7de6-4887-a3c5-ecbcc0867491_1590x1445.png 848w, https://substackcdn.com/image/fetch/$s_!dplQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F329cb989-7de6-4887-a3c5-ecbcc0867491_1590x1445.png 1272w, https://substackcdn.com/image/fetch/$s_!dplQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F329cb989-7de6-4887-a3c5-ecbcc0867491_1590x1445.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 role="img" 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><title></title><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>The key trade-off between the two flavors: <strong>In client-side discovery, the intelligence lives with the client</strong> (each service that calls others must handle discovery logic). <strong>In server-side discovery, the intelligence lives in the network</strong> (the platform or an intermediary handles discovery for you). Both models can achieve high availability and load balancing; which to use often depends on your ecosystem and tooling. In practice, systems like <strong>Kubernetes</strong> or <strong>service mesh</strong> proxies have made server-side discovery very popular (since the platform automates it), whereas libraries like Eureka or Consul&#8217;s API made client-side popular in early microservice architectures (like Netflix&#8217;s). Many environments actually use a mix &#8211; for example, a client might do a DNS lookup (kind of a discovery) which is served by a service mesh sidecar proxy (server-side pattern internally). </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5ybv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd06eadc2-6345-494f-a92b-25583906f31c_1430x1490.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5ybv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd06eadc2-6345-494f-a92b-25583906f31c_1430x1490.png 424w, https://substackcdn.com/image/fetch/$s_!5ybv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd06eadc2-6345-494f-a92b-25583906f31c_1430x1490.png 848w, https://substackcdn.com/image/fetch/$s_!5ybv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd06eadc2-6345-494f-a92b-25583906f31c_1430x1490.png 1272w, https://substackcdn.com/image/fetch/$s_!5ybv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd06eadc2-6345-494f-a92b-25583906f31c_1430x1490.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5ybv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd06eadc2-6345-494f-a92b-25583906f31c_1430x1490.png" width="1430" height="1490" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d06eadc2-6345-494f-a92b-25583906f31c_1430x1490.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1490,&quot;width&quot;:1430,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:185814,&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://iam.slys.dev/i/176729744?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd06eadc2-6345-494f-a92b-25583906f31c_1430x1490.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_!5ybv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd06eadc2-6345-494f-a92b-25583906f31c_1430x1490.png 424w, https://substackcdn.com/image/fetch/$s_!5ybv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd06eadc2-6345-494f-a92b-25583906f31c_1430x1490.png 848w, https://substackcdn.com/image/fetch/$s_!5ybv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd06eadc2-6345-494f-a92b-25583906f31c_1430x1490.png 1272w, https://substackcdn.com/image/fetch/$s_!5ybv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd06eadc2-6345-494f-a92b-25583906f31c_1430x1490.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 role="img" 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><title></title><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 end goal is the same:</strong> the caller gets connected to a living, healthy instance of the target service.</p><h1>&#129518; The heart of discovery &#8212; the service registry</h1><p>Whether client-side or server-side, almost every service discovery system revolves around a <strong>service registry</strong>. This is the heart of discovery: a database (or directory) that holds the <strong>locations of services</strong> and keeps track of which instances are available. Think of the registry as a <strong>dynamic phone book</strong> for all the services in your system - one that is constantly updating itself.</p><p>So how does it work behind the scenes? When each service instance starts up, it <strong>registers itself</strong> with the registry. It provides details like its identity (service name), address (IP and port), and perhaps other metadata (like what version it is, or a health check endpoint). For example, if we have a <strong>User Service</strong>, when a new instance of User Service launches, it will announce &#8220;<em>I am User-Service instance, and I&#8217;m listening on 10.1.2.3:8080</em>&#8221; to the registry. The registry records this entry in its database.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!deaX!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feebe1ee3-7b4c-4b58-ae1b-15b2620f1af4_1679x1713.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!deaX!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feebe1ee3-7b4c-4b58-ae1b-15b2620f1af4_1679x1713.png 424w, https://substackcdn.com/image/fetch/$s_!deaX!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feebe1ee3-7b4c-4b58-ae1b-15b2620f1af4_1679x1713.png 848w, https://substackcdn.com/image/fetch/$s_!deaX!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feebe1ee3-7b4c-4b58-ae1b-15b2620f1af4_1679x1713.png 1272w, https://substackcdn.com/image/fetch/$s_!deaX!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feebe1ee3-7b4c-4b58-ae1b-15b2620f1af4_1679x1713.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!deaX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feebe1ee3-7b4c-4b58-ae1b-15b2620f1af4_1679x1713.png" width="1456" height="1485" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/eebe1ee3-7b4c-4b58-ae1b-15b2620f1af4_1679x1713.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1485,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:168786,&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://iam.slys.dev/i/176729744?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feebe1ee3-7b4c-4b58-ae1b-15b2620f1af4_1679x1713.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_!deaX!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feebe1ee3-7b4c-4b58-ae1b-15b2620f1af4_1679x1713.png 424w, https://substackcdn.com/image/fetch/$s_!deaX!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feebe1ee3-7b4c-4b58-ae1b-15b2620f1af4_1679x1713.png 848w, https://substackcdn.com/image/fetch/$s_!deaX!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feebe1ee3-7b4c-4b58-ae1b-15b2620f1af4_1679x1713.png 1272w, https://substackcdn.com/image/fetch/$s_!deaX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feebe1ee3-7b4c-4b58-ae1b-15b2620f1af4_1679x1713.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 role="img" 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><title></title><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>The registry isn&#8217;t just a static database; it&#8217;s actively maintained. Service instances typically <em>renew</em> their registration periodically (like a heartbeat) or the registry calls them to check if they&#8217;re still alive (more on health checks in the next section). When a service shuts down normally, it <strong>deregisters</strong> itself - essentially saying &#8220;<em>take me off the list</em>&#8221;. If a service crashes or is unreachable, the registry will notice via missing heartbeats or failed health checks and remove that entry after a grace period. This way, the registry always aims to have a <em>fresh list</em> of who&#8217;s out there and healthy.</p><p>Now, when another service (a client) needs to find, say, <em>User Service</em>, it queries the registry: &#8220;<em>Give me the instances for </em><code>User-Service</code>&#8221;. The registry replies with the current list of active instances and their addresses. The client can then use one of those addresses to make the call. If no instances are available, the registry could return an empty result or an error, and the client knows the service is (temporarily) unavailable.</p><p>Some popular <strong>service registry</strong> implementations and tools include:</p><p><strong>HashiCorp Consul</strong> &#8211; a distributed key-value store and registry that supports health checks and offers both REST and DNS interfaces for discovery.</p><p><strong>Netflix Eureka</strong> &#8211; part of Netflix&#8217;s open-source suite, a registry service where clients (usually with a Java client library) register and discover services. Eureka clients also use a heartbeat mechanism to stay registered.</p><p><strong>etcd</strong> &#8211; a distributed key-value store (by CoreOS) that underpins Kubernetes. Kubernetes uses etcd to store all cluster data, including service information for discovery. In Kubernetes, you typically don&#8217;t interact with etcd directly, but it&#8217;s the source of truth for service endpoints.</p><p><strong>Apache Zookeeper</strong> &#8211; an older but rock-solid distributed coordination system, often used in the past for service discovery and configuration in systems like Hadoop or older microservice frameworks. It maintains a hierarchical data store of service names and addresses and can notify watchers of changes.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!jQ80!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc71d73a9-1711-4411-843b-735679719801_2692x1392.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jQ80!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc71d73a9-1711-4411-843b-735679719801_2692x1392.png 424w, https://substackcdn.com/image/fetch/$s_!jQ80!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc71d73a9-1711-4411-843b-735679719801_2692x1392.png 848w, https://substackcdn.com/image/fetch/$s_!jQ80!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc71d73a9-1711-4411-843b-735679719801_2692x1392.png 1272w, https://substackcdn.com/image/fetch/$s_!jQ80!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc71d73a9-1711-4411-843b-735679719801_2692x1392.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jQ80!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc71d73a9-1711-4411-843b-735679719801_2692x1392.png" width="1200" height="620.6043956043956" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c71d73a9-1711-4411-843b-735679719801_2692x1392.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:753,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:204224,&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://iam.slys.dev/i/176729744?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc71d73a9-1711-4411-843b-735679719801_2692x1392.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!jQ80!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc71d73a9-1711-4411-843b-735679719801_2692x1392.png 424w, https://substackcdn.com/image/fetch/$s_!jQ80!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc71d73a9-1711-4411-843b-735679719801_2692x1392.png 848w, https://substackcdn.com/image/fetch/$s_!jQ80!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc71d73a9-1711-4411-843b-735679719801_2692x1392.png 1272w, https://substackcdn.com/image/fetch/$s_!jQ80!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc71d73a9-1711-4411-843b-735679719801_2692x1392.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 role="img" 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><title></title><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>Other technologies and platforms have their own registries: for instance, <strong>Kubernetes</strong> doesn&#8217;t expose etcd directly to you for service discovery, but it effectively has an internal registry of services and endpoints (the Kubernetes control plane ensures that). AWS&#8217;s Elastic Load Balancing and ECS have a form of implicit registry (you register instances in a target group). Similarly, systems like <strong>Apache Mesos/Marathon</strong> had service registries. The pattern is universal &#8211; there&#8217;s always a repository of service locations somewhere.</p><div><hr></div><p><strong>&#128736;&#65039; Which tools are </strong><em><strong>you</strong></em><strong> using?</strong></p><p>Have you tried Consul, Zookeeper, or maybe you&#8217;re wrestling with AWS&#8217;s ELB quirks? I&#8217;d love to hear your thoughts, questions, or stories from the trenches.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/how-systems-find-each-other-service/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/how-systems-find-each-other-service/comments"><span>Leave a comment</span></a></p><div><hr></div><p>Think of the registry as a <strong>phone book that updates itself every second.</strong> It&#8217;s the authoritative source that knows &#8220;<em>what lives where</em>&#8221; at any given moment. Without it, every service would be shouting into the void, or we&#8217;d be back to the bad old days of maintaining long lists of IP addresses in config files (which would never stay accurate). The service registry gives us a single source of truth for service locations, and service discovery is basically every participant agreeing to use that source of truth to find each other.</p><h1>&#128269; Health Checks &#8212; knowing who&#8217;s alive</h1><p>Finding a service is one thing &#8211; but finding a <strong>working</strong> service is another. If our registry simply kept every service that ever registered listed forever, it would quickly accumulate stale entries (dead instances) and mislead clients. That&#8217;s why <strong>health checks</strong> are a crucial part of service discovery.</p><p>A health check is a simple probe (often an HTTP GET to a <code>/health</code> endpoint, a ping, or a heartbeat signal) used to verify that a service instance is <strong>alive and functioning</strong>. Service registries use health checks to keep their data accurate:</p><ul><li><p><strong>Active heartbeats:</strong> Some systems (like Eureka) have the service instances periodically send heartbeats to the registry. If heartbeats stop, the registry marks the instance as dead after a timeout.</p></li><li><p><strong>Pull health checks:</strong> Other systems (like Consul, Zookeeper) have the registry actively ping or check each service at intervals. For example, Consul can be configured with a health check command or HTTP check for each service; if the check fails, Consul will flag that instance as unhealthy.</p></li><li><p><strong>Integration with orchestration:</strong> In platforms like Kubernetes, health status is often integrated &#8211; if a pod fails its liveness or readiness probes, Kubernetes can remove it from service endpoints. That information propagates to discovery (so DNS won&#8217;t include a failing pod, etc.).</p></li></ul><p>The result is that the registry (or discovery system) maintains a list of <strong>healthy</strong> instances. When a client asks for a service, it ideally only gets back instances that are up and passing health checks. If an instance goes down unexpectedly, the health mechanism ensures it will be removed from the registry, often within seconds. Conversely, when an instance comes back or a new one is added, it will start passing health checks and get included.</p><p>Without health checks, service discovery would be giving out potentially bad phone numbers - you&#8217;d call, and nobody picks up. It would be like having a phone book full of businesses that have shut down; you keep dialing dead lines. Thus, any robust discovery system pairs <strong>registration</strong> with <strong>monitoring</strong> of health. Some registries allow a grace period or a TTL (time-to-live) for registrations - a service must renew before the TTL expires or it&#8217;s assumed dead. Others use push-based failure detection. The end goal is the same: <strong>only live services should be discoverable</strong>.</p><p>One more aspect is <strong>health metadata</strong> - sometimes an instance is <em>alive</em> but not <em>healthy</em> to serve (e.g., it&#8217;s overloaded or in maintenance mode). Advanced discovery setups propagate health states (like &#8220;<em>passing</em>&#8221;, &#8220;<em>warning</em>&#8221;, &#8220;<em>failing</em>&#8221;) so that clients can decide to avoid instances that are in warning state, etc. But for most cases, it&#8217;s a binary: in or out.</p><p>So, service discovery is <strong>continuous</strong>. It&#8217;s not a one-time mapping of names to addresses &#8211; it&#8217;s an ever-evolving directory. Registries continuously reconcile the real world (which instances are up) with their internal records. This dynamic nature is what makes service discovery powerful: it turns an unpredictable, changing network into something applications can trust, by <em>constantly expiring and refreshing information</em>. As one source neatly put it: discovery without health checks would leave you &#8220;<em>with a phone book full of disconnected numbers</em>&#8221;, which isn&#8217;t very useful.</p><h1>&#127760; Discovery in the cloud-native world</h1><p>Modern cloud-native platforms have made service discovery <em>almost invisible</em> to developers. If you use Kubernetes or a similar orchestration system, you might be using service discovery features without even realizing it - it just feels like the platform magically makes services reachable by name. But under the hood, it&#8217;s the same principles we&#8217;ve discussed.</p><p>Take <strong>Kubernetes</strong> for example. In Kubernetes, when you deploy a set of pods running &#8220;<em>User Service</em>&#8221;, you typically define a <strong>Service</strong> object (let&#8217;s say named &#8220;<em>user-service</em>&#8221;). Kubernetes will allocate a stable virtual IP address for that Service (within the cluster) and set up a DNS name like <code>user-service.default.svc.cluster.local</code> (assuming it&#8217;s in the &#8220;<em>default</em>&#8221; namespace). Now any other service in the cluster can simply refer to</p><pre><code>http://user-service </code></pre><p>(Kubernetes&#8217; DNS can shorten the full domain) and get routed to one of the pods. It feels like magic &#8211; you didn&#8217;t personally implement a registry or a lookup &#8211; but Kubernetes did it for you.</p><p>What&#8217;s happening behind the scenes? Kubernetes uses a few cooperating components for discovery:</p><ul><li><p><strong>Etcd as registry:</strong> Kubernetes&#8217; control plane (specifically the API server) uses <strong>etcd</strong> as its backing store for all cluster data. This includes the endpoints for each service. Whenever pods come and go, the Kubernetes controllers update the list of endpoints for a Service (which is stored in etcd).<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a> In essence, etcd is the service registry, keeping track of which pod IPs are tied to &#8220;user-service&#8221; at any time.</p></li><li><p><strong>DNS and environment variables:</strong> Kubernetes runs an internal DNS service (like CoreDNS) that watches for service changes. It automatically creates DNS A records so that <code>user-service.default.svc.cluster.local</code> maps to the Service&#8217;s cluster IP. It also can inject environment variables into pods (like <code>USER_SERVICE_SERVICE_HOST=10.3.245.7</code>) giving another way to find the service IP. This means as a developer you can just use the service name and trust that DNS will resolve it to the right IP.</p></li><li><p><strong>Kube-proxy or networking for routing:</strong> The cluster IP itself (and corresponding DNS name) is virtual &#8211; it&#8217;s handled by <code>kube-proxy</code> on each node (or by advanced routing in newer implementations like kube-proxy IPVS or Cilium). Kube-proxy maintains iptables or IPVS rules that map the Service IP to the set of current Pod IPs for that service. When you hit the Service IP, the request gets load balanced to one of the pod endpoints that&#8217;s actually alive. If pods are added or removed, kube-proxy updates the rules. This is server-side discovery internalized: your request goes to a stable IP, and the cluster networking finds an appropriate instance.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5NfC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac74b8b6-fa80-4335-ac56-0f636d8de245_2494x1723.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5NfC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac74b8b6-fa80-4335-ac56-0f636d8de245_2494x1723.png 424w, https://substackcdn.com/image/fetch/$s_!5NfC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac74b8b6-fa80-4335-ac56-0f636d8de245_2494x1723.png 848w, https://substackcdn.com/image/fetch/$s_!5NfC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac74b8b6-fa80-4335-ac56-0f636d8de245_2494x1723.png 1272w, https://substackcdn.com/image/fetch/$s_!5NfC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac74b8b6-fa80-4335-ac56-0f636d8de245_2494x1723.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5NfC!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac74b8b6-fa80-4335-ac56-0f636d8de245_2494x1723.png" width="1200" height="829.1208791208791" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ac74b8b6-fa80-4335-ac56-0f636d8de245_2494x1723.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1006,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:301004,&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://iam.slys.dev/i/176729744?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac74b8b6-fa80-4335-ac56-0f636d8de245_2494x1723.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!5NfC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac74b8b6-fa80-4335-ac56-0f636d8de245_2494x1723.png 424w, https://substackcdn.com/image/fetch/$s_!5NfC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac74b8b6-fa80-4335-ac56-0f636d8de245_2494x1723.png 848w, https://substackcdn.com/image/fetch/$s_!5NfC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac74b8b6-fa80-4335-ac56-0f636d8de245_2494x1723.png 1272w, https://substackcdn.com/image/fetch/$s_!5NfC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fac74b8b6-fa80-4335-ac56-0f636d8de245_2494x1723.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 role="img" 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><title></title><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>The upshot is that <strong>the platform handles registration and discovery for you</strong>. When a new pod comes up, Kubernetes will automatically add it to the endpoints of the Service (registering it). If a pod dies, it&#8217;s removed. Health checks (readiness probes) integrate so that if a pod is not ready, it&#8217;s temporarily removed from endpoints. All of this happens without the service authors writing any discovery code. You just name the service you want to call, and Kubernetes ensures that name resolves to something that works. It&#8217;s the same idea of service discovery, but baked into the infrastructure as an <strong>automated, built-in feature</strong>.</p><p>Service meshes (like <strong>Istio</strong>, <strong>Linkerd</strong>, etc.) go even further. They often leverage the existing discovery (from Kubernetes or another system) but add a layer of proxies that can do more intelligent routing (like per-request load balancing, traffic shifting, etc.). Even in those cases, the fundamental discovery (knowing what instances exist for a service) still often comes from the service registry (e.g., Istio taps into Kubernetes&#8217; service registry and adds its own logic on top).</p><p>To give a concrete example: imagine our <em>User Service</em> in Kubernetes. If it&#8217;s scaled to 5 pods, the Kubernetes registry (etcd) knows there are 5 endpoints. The DNS name <code>user-service.default.svc.cluster.local</code> will resolve (round-robin or via kube-proxy VIP) to one of those pod IPs. From our perspective, we just do <code>GET http://user-service:8080/api/profile</code> and we reach one of the five pods. If we deploy a new version of User Service (blue-green deploy) under the hood Kubernetes might switch the endpoints to 5 new pods and remove the old 5 &#8211; but as a caller, you still hit <code>user-service</code> and magically get the new pods. No code change, no manual update &#8211; discovery handled it. It&#8217;s &#8220;<em>magic</em>&#8221; in the sense that you don&#8217;t have to think about it, but underneath it&#8217;s the same machinery: a constantly updated mapping of service name to instance addresses.</p><div class="pullquote"><p>&#10145;&#65039; <strong>Mini insight:</strong> In modern cloud-native systems, what feels like &#8220;magic&#8221; is really just automation doing the tedious work for you. Service discovery in Kubernetes (and similar platforms) is essentially automated service registry + automated client or server-side discovery. You <em>could</em> do it yourself, but you don&#8217;t have to, because the platform engineers have done it once in a generic way for everyone. The principles remain the same: separate naming from addressing, keep track of health, update everyone&#8217;s &#8220;phone book&#8221; continuously.</p></div><h1>&#129513; When things go wrong</h1><p>Service discovery makes distributed systems feasible, but it doesn&#8217;t make them <strong>infallible</strong>. Like any distributed system component, a service discovery system can experience issues. It&#8217;s important to be aware of common failure modes and challenges:</p><ul><li><p><strong>Stale Entries:</strong> There&#8217;s a period of time between a service going down and the registry noticing. If that interval is too long (or if heartbeats/health checks fail to promptly remove a dead instance), clients might still be sent to an address that&#8217;s no longer valid. This results in errors when calling a service that is actually down. For example, if a registry has a long TTL or a health check that runs once a minute, there could be up to a minute where a dead service is still &#8220;discoverable&#8221;. The solution is to use aggressive health checks and shorter TTLs so that information is refreshed quickly. Still, a balance is needed: make it too short and you might flap or remove instances that have brief hiccups. Tuning is key.</p></li><li><p><strong>Single Point of Failure / Overloaded Registry:</strong> The service registry itself is a critical component. If the registry goes down, the whole discovery mechanism grinds to a halt (at that point, services can&#8217;t find each other, except through perhaps cached data which will become outdated). Also, if the registry is under heavy load (imagine hundreds of services registering and hundreds of clients querying every second), it can become a bottleneck. That&#8217;s why registries must be designed to be <strong>highly available and scalable</strong>. Typically, they are run as clusters themselves (e.g., multiple Consul servers, Eureka in cluster mode) to avoid a single point of failure. Caching on the client side can mitigate read load &#8211; many discovery libraries cache the last known good addresses for a service and fall back to them if the registry is momentarily unreachable. But ultimately, you need to treat the registry like an absolutely critical infra component (because it is). If it fails or lags, it&#8217;s like the phone book is missing pages or not updating &#8211; chaos can ensue.</p></li><li><p><strong>Network Partitions:</strong> In a distributed system, sometimes parts of the network can become isolated (the dreaded &#8220;<em>split brain</em>&#8221; scenario). In such a case, you might have <strong>partitioned views of service discovery</strong>. For example, half of the instances and half of the clients can&#8217;t reach the other half. Each side might have a registry that thinks the other side&#8217;s services are down. This can lead to situations where services that are actually healthy (on the other side of the partition) are seen as unavailable. Or worse, when the partition heals, two registries might have conflicting data. Robust systems handle this with techniques like <strong>zone-aware routing</strong> (so clients prefer local instances), or by ensuring the registry has a consistent view when partitioned (which often devolves to choosing one side as the source of truth). Network partitions are tricky &#8211; essentially, if your discovery mechanism itself is distributed, it has to deal with consensus and partition tolerance (per the CAP theorem). Zookeeper, for instance, will refuse to operate if it loses quorum (to avoid serving stale data). Eureka by default is more AP (available), which means it might serve stale data during a partition rather than be unavailable.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a> There&#8217;s no silver bullet; it&#8217;s the classic trade-off.</p></li><li><p><strong>Consistency and Convergence Delays:</strong> In larger systems, there may be a slight delay from the moment a service registers/deregisters to the moment all clients become aware. If your registry uses a push model (e.g., it notifies clients or a sidecar of changes), there&#8217;s propagation time. If clients poll periodically, there&#8217;s a window of staleness. Usually these delays are seconds or less, but in extreme cases they can cause brief inconsistencies (one client thinks there are 5 instances, another thinks 4). Most of the time this isn&#8217;t a huge problem (a request might fail and then retry and succeed), but it&#8217;s good to design with the expectation that discovery info is <strong>eventually consistent</strong> rather than instantly consistent.</p></li><li><p><strong>Dependency Loops:</strong> This is more of an architectural pitfall &#8211; if Service A and Service B depend on each other to start up via discovery, you can get a deadlock. For example, Service A won&#8217;t register as ready until it talks to B, and B won&#8217;t start until A is available. If both are waiting on discovery, they&#8217;ll wait forever. This is not the registry&#8217;s fault per se, but a usage pitfall. The way to avoid it is to design services such that there aren&#8217;t circular startup dependencies (or break the loop with some timeout or default behavior). It&#8217;s like two friends each waiting for the other to call first &#8211; sometimes someone has to just proceed.</p></li><li><p><strong>Security and Trust:</strong> If not properly secured, a malicious actor could potentially register fake services or deregister others. Real-world service registries often have authentication and ACLs, and in zero-trust environments, discovery info might be distributed via secure channels. This isn&#8217;t a &#8220;<em>when things go wrong</em>&#8221; in the failure sense, but it&#8217;s a risk if not addressed. After all, if the phone book can be tampered with, you might call the wrong number (and that number might be an attacker).</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ntaf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4d08152-d8d4-4f53-bfa6-d4c4036b6efd_2893x2065.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ntaf!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4d08152-d8d4-4f53-bfa6-d4c4036b6efd_2893x2065.png 424w, https://substackcdn.com/image/fetch/$s_!Ntaf!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4d08152-d8d4-4f53-bfa6-d4c4036b6efd_2893x2065.png 848w, https://substackcdn.com/image/fetch/$s_!Ntaf!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4d08152-d8d4-4f53-bfa6-d4c4036b6efd_2893x2065.png 1272w, https://substackcdn.com/image/fetch/$s_!Ntaf!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4d08152-d8d4-4f53-bfa6-d4c4036b6efd_2893x2065.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ntaf!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4d08152-d8d4-4f53-bfa6-d4c4036b6efd_2893x2065.png" width="1200" height="856.3186813186813" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a4d08152-d8d4-4f53-bfa6-d4c4036b6efd_2893x2065.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1039,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:410620,&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://iam.slys.dev/i/176729744?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4d08152-d8d4-4f53-bfa6-d4c4036b6efd_2893x2065.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Ntaf!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4d08152-d8d4-4f53-bfa6-d4c4036b6efd_2893x2065.png 424w, https://substackcdn.com/image/fetch/$s_!Ntaf!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4d08152-d8d4-4f53-bfa6-d4c4036b6efd_2893x2065.png 848w, https://substackcdn.com/image/fetch/$s_!Ntaf!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4d08152-d8d4-4f53-bfa6-d4c4036b6efd_2893x2065.png 1272w, https://substackcdn.com/image/fetch/$s_!Ntaf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4d08152-d8d4-4f53-bfa6-d4c4036b6efd_2893x2065.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 role="img" 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><title></title><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>To sum up, service discovery systems are themselves distributed systems. They have to be designed with failure in mind. As one metaphor would put it: even the best p</p><p>hone book is useless if the printing press fails halfway (or if the post office loses half the pages). In practice, solutions include running multiple registry servers (with consensus or leader election), client-side caching and fallbacks, health check tuning, and partition-aware setups (like multi-region registries that sync gradually). The good news is that mature solutions like Consul, Eureka, etcd, and Zookeeper have thought through many of these edge cases &#8211; but as an engineer, it&#8217;s still wise to be aware of them when designing your system&#8217;s architecture.</p><h1>&#128172; Service Discovery as a philosophy</h1><p>At this point, we&#8217;ve covered the mechanics of service discovery. Let&#8217;s step back and view it from a higher altitude &#8211; almost philosophically.</p><p>In a way, <strong>Service Discovery isn&#8217;t magic - it&#8217;s trust</strong>. It&#8217;s a silent agreement among all the services in a system, a sort of social contract of software: <em>&#8220;I&#8217;ll tell you where I am, if you promise to remember and find me when I move.&#8221;</em> Every service that comes online says &#8220;<em>Here I am, here&#8217;s how to reach me.</em>&#8221; The discovery system (and by extension all the other services) replies, &#8220;<em>Got it. We&#8217;ll keep track. If you go away or relocate, just let us know (or we&#8217;ll find out), and we&#8217;ll adapt.</em>&#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_!PnVC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F292c3d16-e42e-4a63-8406-6e36e01749ac_2022x1960.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!PnVC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F292c3d16-e42e-4a63-8406-6e36e01749ac_2022x1960.png 424w, https://substackcdn.com/image/fetch/$s_!PnVC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F292c3d16-e42e-4a63-8406-6e36e01749ac_2022x1960.png 848w, https://substackcdn.com/image/fetch/$s_!PnVC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F292c3d16-e42e-4a63-8406-6e36e01749ac_2022x1960.png 1272w, https://substackcdn.com/image/fetch/$s_!PnVC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F292c3d16-e42e-4a63-8406-6e36e01749ac_2022x1960.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!PnVC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F292c3d16-e42e-4a63-8406-6e36e01749ac_2022x1960.png" width="1456" height="1411" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/292c3d16-e42e-4a63-8406-6e36e01749ac_2022x1960.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1411,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:235325,&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://iam.slys.dev/i/176729744?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F292c3d16-e42e-4a63-8406-6e36e01749ac_2022x1960.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_!PnVC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F292c3d16-e42e-4a63-8406-6e36e01749ac_2022x1960.png 424w, https://substackcdn.com/image/fetch/$s_!PnVC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F292c3d16-e42e-4a63-8406-6e36e01749ac_2022x1960.png 848w, https://substackcdn.com/image/fetch/$s_!PnVC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F292c3d16-e42e-4a63-8406-6e36e01749ac_2022x1960.png 1272w, https://substackcdn.com/image/fetch/$s_!PnVC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F292c3d16-e42e-4a63-8406-6e36e01749ac_2022x1960.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 role="img" 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><title></title><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>This mutual trust &#8211; that services will announce themselves and the system will faithfully keep that information up-to-date &#8211; is what allows <strong>order to emerge from chaos</strong>. In a vast sea of ephemeral instances popping in and out of existence, service discovery is the handshake that keeps everything coordinated. It turns what would be a cacophony of &#8220;<em>hello, where are you?</em>&#8221; into a well-orchestrated conversation.</p><p>In practical terms, service discovery embodies the principle of <strong>loose coupling</strong>. Services don&#8217;t need to know the internal details or exact location of others, only a stable identity. It&#8217;s like focusing on <em>who</em> you need, not <em>where</em> they are. This decoupling of identity from location is deeply powerful &#8211; it underpins the scalability and resilience of microservices. You can deploy a hundred instances or scale down to one, move them across data centers, upgrade them, or take them down for maintenance, all without breaking the contract. As long as you uphold the discovery protocol (register/unregister or pass health checks), the rest of the system will gracefully adapt.</p><p>So, beyond the technicalities, think of service discovery as the <strong>invisible glue</strong> or the <strong>neural network</strong> of your architecture&#8217;s brain. It&#8217;s constantly sensing and communicating changes in the system&#8217;s topology so that every part knows how to reach every other part. It is, fundamentally, about <strong>ensuring connectivity</strong> in a fluid world. It&#8217;s not magic at all &#8211; it&#8217;s solid engineering &#8211; but from the outside it can sure feel magical that no matter how much things move around, nothing gets lost.</p><blockquote><p>In summary: <em>Service discovery is the unsung hero that turns chaos into coordination &#8212; the invisible handshake that keeps distributed systems together.</em></p></blockquote><div><hr></div><p><strong>Know someone who&#8217;s just getting into backend development or cloud architecture</strong></p><p>If this post helped you, pass it along - help them level up too. &#128071;</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/leaderboard?&amp;utm_source=post&quot;,&quot;text&quot;:&quot;Refer a friend&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/leaderboard?&amp;utm_source=post"><span>Refer a friend</span></a></p><div><hr></div><h1>&#9997;&#65039; Summary</h1><p><strong>In distributed systems, nothing stays put. </strong>Unlike a monolith (where everything&#8217;s in one place), microservice instances are constantly changing &#8211; scaling up, shutting down, moving across hosts. Hard-coding their locations isn&#8217;t feasible.</p><p><strong>Service Discovery is the solution.</strong> It allows services to find each other <strong>dynamically</strong>, asking &#8220;<em>Where is X now?</em>&#8221; and getting a current answer. This separates the <em>service identity</em> (fixed) from the <em>service location</em> (fluid).</p><p><strong>Two discovery models &#8211; client vs server side.</strong> In <em>client-side discovery</em>, the calling service does the work of looking up the target&#8217;s location (e.g., using a library to query a registry). In <em>server-side discovery</em>, the caller just goes to a fixed entry point (like a load balancer) and that component looks up and forwards to the target. Both achieve the same end result, and many systems use a mix of both patterns.</p><p><strong>Service Registry as the source of truth.</strong> A registry is like a constantly updated phone book of all service instances. Services register themselves on startup and deregister on shutdown (or are removed if they crash). Examples include Consul, Eureka, etcd, Zookeeper, or even Kubernetes&#8217;s built-in etcd-based registry. The registry stores where each service lives at the moment.</p><p><strong>Health checks keep it accurate.</strong> The discovery system performs regular health checks or heartbeats to ensure that only healthy, alive instances are considered. Unhealthy ones are dropped until they recover. This way, &#8220;<em>discovering a service</em>&#8221; usually means discovering an <strong>available</strong> service.</p><p><strong>Cloud-native platforms automate discovery.</strong> Kubernetes, for instance, gives every service a stable DNS name and does the discovery and load balancing under the hood. Developers don&#8217;t have to manually query registries &#8211; the platform&#8217;s networking does it. It feels like magic, but it&#8217;s really just the same service discovery principles applied automatically.</p><p><strong>Things can still go wrong!</strong> Be mindful of issues like stale registry data, registry downtime, network partitions, etc., when designing your system. Use robust, highly available registry setups and perhaps client-side caching or fallbacks. And avoid circular dependencies where services depend on each other&#8217;s presence in awkward ways.</p><p>Service discovery turns &#8220;<em>finding</em>&#8221; into a first-class capability of your system. It answers the question &#8220;<em>Who serves this request?</em>&#8221; in real-time, every time. By doing so, it enables <em>trust</em> among moving parts &#8211; every service can move about freely, confident that others will still be able to find it. In the end, service discovery is what allows distributed systems to be dynamic, scalable, and fault-tolerant <strong>without losing connectivity</strong>. It&#8217;s not magic, but it sure makes the impossible possible.</p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p><a href="https://microservices.io/patterns/service-registry.html">Pattern: Service registry</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p><a href="https://devopscube.com/service-discovery-explained/">What is Service Discovery? [Explained With Examples]</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p><a href="https://medium.com/@tharinduimalka915/service-discovery-in-microservices-architecture-ea41e695b3df">Service Discovery in Microservices Architecture</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-4" href="#footnote-anchor-4" class="footnote-number" contenteditable="false" target="_self">4</a><div class="footnote-content"><p><a href="https://kubex.ai/kubernetes-autoscaling/kubernetes-service-discovery/">Kubernetes Service Discovery</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-5" href="#footnote-anchor-5" class="footnote-number" contenteditable="false" target="_self">5</a><div class="footnote-content"><p><a href="https://medium.com/knerd/eureka-why-you-shouldnt-use-zookeeper-for-service-discovery-4932c5c7e764">Eureka! Why You Shouldn&#8217;t Use ZooKeeper for Service Discovery</a></p></div></div>]]></content:encoded></item><item><title><![CDATA[How to learn System Design without getting overwhelmed]]></title><description><![CDATA[A beginner-friendly roadmap of blogs, books, and experts to help you go from confused to confident]]></description><link>https://iam.slys.dev/p/how-to-learn-system-design-without</link><guid isPermaLink="false">https://iam.slys.dev/p/how-to-learn-system-design-without</guid><dc:creator><![CDATA[Jakub Slys 🤖]]></dc:creator><pubDate>Mon, 05 Jan 2026 21:11:27 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!MtK7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2a67bd4-f225-470e-9ee8-fbb5acbeb221_1536x1024.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_!MtK7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2a67bd4-f225-470e-9ee8-fbb5acbeb221_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MtK7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2a67bd4-f225-470e-9ee8-fbb5acbeb221_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!MtK7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2a67bd4-f225-470e-9ee8-fbb5acbeb221_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!MtK7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2a67bd4-f225-470e-9ee8-fbb5acbeb221_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!MtK7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2a67bd4-f225-470e-9ee8-fbb5acbeb221_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!MtK7!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2a67bd4-f225-470e-9ee8-fbb5acbeb221_1536x1024.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a2a67bd4-f225-470e-9ee8-fbb5acbeb221_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:3069146,&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://iam.slys.dev/i/182873025?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2a67bd4-f225-470e-9ee8-fbb5acbeb221_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!MtK7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2a67bd4-f225-470e-9ee8-fbb5acbeb221_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!MtK7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2a67bd4-f225-470e-9ee8-fbb5acbeb221_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!MtK7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2a67bd4-f225-470e-9ee8-fbb5acbeb221_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!MtK7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2a67bd4-f225-470e-9ee8-fbb5acbeb221_1536x1024.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 role="img" 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><title></title><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>Imagine trying to assemble a giant jigsaw puzzle without the picture on the box. You have hundreds of pieces, but no clue what the final image looks like. &#128517; When I first started coding, I <em>definitely</em> felt that way. The tech world was a pile of scattered pieces - programming languages, tools, theories - and I wasn&#8217;t sure how to fit them together. The good news is, you don&#8217;t have to solve the puzzle alone. Plenty of developers have left us a &#8220;<em>picture on the box</em>&#8221; in the form of blogs, open-source code, and classic books. These resources act as guideposts, lighting the path so you can focus on learning and building. In this post, I&#8217;ll share some of the most helpful resources (and how to use them) that will make your programming journey more accessible and <strong>fun</strong>.</p><h1>Company Tech Blogs &#128640;</h1><p>One great way to learn how real-world systems work is by following the engineering blogs of major tech companies. These blogs are like getting a backstage tour of how the pros build software at scale. Companies often publish articles about their architecture decisions, performance debugging adventures, and new technologies they&#8217;re exploring, giving you insight into industry best practices.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="http://netflixtechblog.com" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6oVR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e1e863-92f2-4e39-a517-8d9180534fa8_940x529.jpeg 424w, https://substackcdn.com/image/fetch/$s_!6oVR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e1e863-92f2-4e39-a517-8d9180534fa8_940x529.jpeg 848w, https://substackcdn.com/image/fetch/$s_!6oVR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e1e863-92f2-4e39-a517-8d9180534fa8_940x529.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!6oVR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e1e863-92f2-4e39-a517-8d9180534fa8_940x529.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6oVR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e1e863-92f2-4e39-a517-8d9180534fa8_940x529.jpeg" width="940" height="529" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/32e1e863-92f2-4e39-a517-8d9180534fa8_940x529.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:529,&quot;width&quot;:940,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:21281,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:&quot;http://netflixtechblog.com&quot;,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/182873025?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e1e863-92f2-4e39-a517-8d9180534fa8_940x529.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6oVR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e1e863-92f2-4e39-a517-8d9180534fa8_940x529.jpeg 424w, https://substackcdn.com/image/fetch/$s_!6oVR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e1e863-92f2-4e39-a517-8d9180534fa8_940x529.jpeg 848w, https://substackcdn.com/image/fetch/$s_!6oVR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e1e863-92f2-4e39-a517-8d9180534fa8_940x529.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!6oVR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32e1e863-92f2-4e39-a517-8d9180534fa8_940x529.jpeg 1456w" sizes="100vw"></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 role="img" 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><title></title><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><h2><strong>Netflix TechBlog</strong></h2><blockquote><p><a href="http://netflixtechblog.com">netflixtechblog.com</a></p></blockquote><p>Netflix&#8217;s engineering blog shares how Netflix designs, builds, and operates its large-scale, cloud-native systems. Posts cover real-world challenges in streaming, microservices, resilience (like <em>Chaos Engineering</em>), and data pipelines - great case studies of scalable architectures in practice.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="http://engineering.fb.com" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!x8z7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc48f5ea-7c7f-45f3-af5d-ccd00e3fa02a_4292x2416.jpeg 424w, https://substackcdn.com/image/fetch/$s_!x8z7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc48f5ea-7c7f-45f3-af5d-ccd00e3fa02a_4292x2416.jpeg 848w, https://substackcdn.com/image/fetch/$s_!x8z7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc48f5ea-7c7f-45f3-af5d-ccd00e3fa02a_4292x2416.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!x8z7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc48f5ea-7c7f-45f3-af5d-ccd00e3fa02a_4292x2416.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!x8z7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc48f5ea-7c7f-45f3-af5d-ccd00e3fa02a_4292x2416.jpeg" width="1456" height="820" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dc48f5ea-7c7f-45f3-af5d-ccd00e3fa02a_4292x2416.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:820,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:313224,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:&quot;http://engineering.fb.com&quot;,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/182873025?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc48f5ea-7c7f-45f3-af5d-ccd00e3fa02a_4292x2416.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!x8z7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc48f5ea-7c7f-45f3-af5d-ccd00e3fa02a_4292x2416.jpeg 424w, https://substackcdn.com/image/fetch/$s_!x8z7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc48f5ea-7c7f-45f3-af5d-ccd00e3fa02a_4292x2416.jpeg 848w, https://substackcdn.com/image/fetch/$s_!x8z7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc48f5ea-7c7f-45f3-af5d-ccd00e3fa02a_4292x2416.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!x8z7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc48f5ea-7c7f-45f3-af5d-ccd00e3fa02a_4292x2416.jpeg 1456w" sizes="100vw"></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 role="img" 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><title></title><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><h2><strong>Engineering at Meta</strong></h2><blockquote><p><a href="http://engineering.fb.com">engineering.fb.com</a></p></blockquote><p>Meta&#8217;s official engineering blog discusses how Facebook&#8217;s infrastructure and services operate at billions-of-users scale. It offers deep dives into distributed systems behind Facebook, Instagram, WhatsApp, etc., covering topics like scaling backend services, data storage, AI infrastructure, and reliability at massive scale.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://www.uber.com/blog/engineering/" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NqJJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F12d0e26c-f489-40ff-b221-e730426a2582_8768x5337.png 424w, https://substackcdn.com/image/fetch/$s_!NqJJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F12d0e26c-f489-40ff-b221-e730426a2582_8768x5337.png 848w, https://substackcdn.com/image/fetch/$s_!NqJJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F12d0e26c-f489-40ff-b221-e730426a2582_8768x5337.png 1272w, https://substackcdn.com/image/fetch/$s_!NqJJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F12d0e26c-f489-40ff-b221-e730426a2582_8768x5337.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NqJJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F12d0e26c-f489-40ff-b221-e730426a2582_8768x5337.png" width="1456" height="886" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/12d0e26c-f489-40ff-b221-e730426a2582_8768x5337.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;:915020,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:&quot;https://www.uber.com/blog/engineering/&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/182873025?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F12d0e26c-f489-40ff-b221-e730426a2582_8768x5337.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_!NqJJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F12d0e26c-f489-40ff-b221-e730426a2582_8768x5337.png 424w, https://substackcdn.com/image/fetch/$s_!NqJJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F12d0e26c-f489-40ff-b221-e730426a2582_8768x5337.png 848w, https://substackcdn.com/image/fetch/$s_!NqJJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F12d0e26c-f489-40ff-b221-e730426a2582_8768x5337.png 1272w, https://substackcdn.com/image/fetch/$s_!NqJJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F12d0e26c-f489-40ff-b221-e730426a2582_8768x5337.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 role="img" 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><title></title><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><h2><strong>Uber Engineering Blog</strong></h2><blockquote><p><a href="https://www.uber.com/blog/engineering/">uber.com/blog/engineering</a></p></blockquote><p>Uber&#8217;s tech blog provides detailed articles on the architecture powering its real-time ride-sharing platform. It explores how Uber handles high volumes of location data and requests, with posts on microservices, geospatial databases, load balancing, and reliability techniques that keep their systems running 24/7.</p><p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://blog.cloudflare.com" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2qXW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83a34f1a-1fb2-4f61-b9db-0695959f5537_1277x431.jpeg 424w, https://substackcdn.com/image/fetch/$s_!2qXW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83a34f1a-1fb2-4f61-b9db-0695959f5537_1277x431.jpeg 848w, https://substackcdn.com/image/fetch/$s_!2qXW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83a34f1a-1fb2-4f61-b9db-0695959f5537_1277x431.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!2qXW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83a34f1a-1fb2-4f61-b9db-0695959f5537_1277x431.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2qXW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83a34f1a-1fb2-4f61-b9db-0695959f5537_1277x431.jpeg" width="1277" height="431" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/83a34f1a-1fb2-4f61-b9db-0695959f5537_1277x431.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:431,&quot;width&quot;:1277,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:82648,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:&quot;https://blog.cloudflare.com&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/182873025?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83a34f1a-1fb2-4f61-b9db-0695959f5537_1277x431.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!2qXW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83a34f1a-1fb2-4f61-b9db-0695959f5537_1277x431.jpeg 424w, https://substackcdn.com/image/fetch/$s_!2qXW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83a34f1a-1fb2-4f61-b9db-0695959f5537_1277x431.jpeg 848w, https://substackcdn.com/image/fetch/$s_!2qXW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83a34f1a-1fb2-4f61-b9db-0695959f5537_1277x431.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!2qXW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83a34f1a-1fb2-4f61-b9db-0695959f5537_1277x431.jpeg 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 role="img" 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><title></title><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><h2><strong>The Cloudflare Blog</strong></h2><blockquote><p><a href="https://blog.cloudflare.com">blog.cloudflare.com</a></p></blockquote><p>Cloudflare&#8217;s engineering blog is known for accessible explanations of internet-scale infrastructure. It covers how they build a fast, distributed CDN and security network, with topics like DNS and edge computing, DDoS mitigation, performance optimizations, and other systems-level insights for building a reliable global service.</p><p></p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://engineering.linkedin.com" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jH5Y!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd51b79b8-e507-4410-9c56-f83e19b31ba4_2212x540.png 424w, https://substackcdn.com/image/fetch/$s_!jH5Y!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd51b79b8-e507-4410-9c56-f83e19b31ba4_2212x540.png 848w, https://substackcdn.com/image/fetch/$s_!jH5Y!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd51b79b8-e507-4410-9c56-f83e19b31ba4_2212x540.png 1272w, https://substackcdn.com/image/fetch/$s_!jH5Y!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd51b79b8-e507-4410-9c56-f83e19b31ba4_2212x540.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jH5Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd51b79b8-e507-4410-9c56-f83e19b31ba4_2212x540.png" width="1456" height="355" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d51b79b8-e507-4410-9c56-f83e19b31ba4_2212x540.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:355,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:25367,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:&quot;https://engineering.linkedin.com&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/182873025?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd51b79b8-e507-4410-9c56-f83e19b31ba4_2212x540.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_!jH5Y!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd51b79b8-e507-4410-9c56-f83e19b31ba4_2212x540.png 424w, https://substackcdn.com/image/fetch/$s_!jH5Y!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd51b79b8-e507-4410-9c56-f83e19b31ba4_2212x540.png 848w, https://substackcdn.com/image/fetch/$s_!jH5Y!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd51b79b8-e507-4410-9c56-f83e19b31ba4_2212x540.png 1272w, https://substackcdn.com/image/fetch/$s_!jH5Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd51b79b8-e507-4410-9c56-f83e19b31ba4_2212x540.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><h2><strong>LinkedIn Engineering</strong></h2><blockquote><p><a href="https://engineering.linkedin.com">engineering.linkedin.com</a></p></blockquote><p>LinkedIn&#8217;s engineering blog shares how the professional network designs its backend systems and data pipelines. It features posts on search index scaling, feed generation, big data infrastructure (like Kafka and Gobblin), AI recommendations, and general best practices for building distributed, data-intensive applications.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://aws.amazon.com/blogs/architecture/" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7fbV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F587aa6de-d1a2-4d78-bbb9-1862b8481b45_1510x692.png 424w, https://substackcdn.com/image/fetch/$s_!7fbV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F587aa6de-d1a2-4d78-bbb9-1862b8481b45_1510x692.png 848w, https://substackcdn.com/image/fetch/$s_!7fbV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F587aa6de-d1a2-4d78-bbb9-1862b8481b45_1510x692.png 1272w, https://substackcdn.com/image/fetch/$s_!7fbV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F587aa6de-d1a2-4d78-bbb9-1862b8481b45_1510x692.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7fbV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F587aa6de-d1a2-4d78-bbb9-1862b8481b45_1510x692.png" width="1456" height="667" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/587aa6de-d1a2-4d78-bbb9-1862b8481b45_1510x692.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:667,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:78726,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:&quot;https://aws.amazon.com/blogs/architecture/&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/182873025?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F587aa6de-d1a2-4d78-bbb9-1862b8481b45_1510x692.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_!7fbV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F587aa6de-d1a2-4d78-bbb9-1862b8481b45_1510x692.png 424w, https://substackcdn.com/image/fetch/$s_!7fbV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F587aa6de-d1a2-4d78-bbb9-1862b8481b45_1510x692.png 848w, https://substackcdn.com/image/fetch/$s_!7fbV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F587aa6de-d1a2-4d78-bbb9-1862b8481b45_1510x692.png 1272w, https://substackcdn.com/image/fetch/$s_!7fbV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F587aa6de-d1a2-4d78-bbb9-1862b8481b45_1510x692.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 role="img" 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><title></title><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><h2><strong>AWS Architecture Blog</strong></h2><blockquote><p><a href="https://aws.amazon.com/blogs/architecture/">aws.amazon.com/blogs/architecture</a></p></blockquote><p>AWS&#8217;s official architecture blog covers cloud design patterns and best practices. It&#8217;s useful for learning how to design scalable, highly available systems on the cloud. Posts include reference architectures, case studies, and tips on microservices, serverless, database scaling, caching, and more &#8211; straight from AWS solution architects.</p><p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://stripe.com/blog/engineering" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pWoN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf189d59-56ea-47b7-86e1-7889f6d74f3c_3000x1249.png 424w, https://substackcdn.com/image/fetch/$s_!pWoN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf189d59-56ea-47b7-86e1-7889f6d74f3c_3000x1249.png 848w, https://substackcdn.com/image/fetch/$s_!pWoN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf189d59-56ea-47b7-86e1-7889f6d74f3c_3000x1249.png 1272w, https://substackcdn.com/image/fetch/$s_!pWoN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf189d59-56ea-47b7-86e1-7889f6d74f3c_3000x1249.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pWoN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf189d59-56ea-47b7-86e1-7889f6d74f3c_3000x1249.png" width="1456" height="606" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/df189d59-56ea-47b7-86e1-7889f6d74f3c_3000x1249.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:606,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:60363,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:&quot;https://stripe.com/blog/engineering&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/182873025?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf189d59-56ea-47b7-86e1-7889f6d74f3c_3000x1249.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_!pWoN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf189d59-56ea-47b7-86e1-7889f6d74f3c_3000x1249.png 424w, https://substackcdn.com/image/fetch/$s_!pWoN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf189d59-56ea-47b7-86e1-7889f6d74f3c_3000x1249.png 848w, https://substackcdn.com/image/fetch/$s_!pWoN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf189d59-56ea-47b7-86e1-7889f6d74f3c_3000x1249.png 1272w, https://substackcdn.com/image/fetch/$s_!pWoN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf189d59-56ea-47b7-86e1-7889f6d74f3c_3000x1249.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 role="img" 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><title></title><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><h2><strong>Stripe Engineering Blog</strong></h2><blockquote><p><a href="https://stripe.com/blog/engineering">stripe.com/blog/engineering</a></p></blockquote><p>Stripe&#8217;s engineering blog discusses how they build and scale a global payments platform. It delves into topics like building reliable financial systems, API design, infrastructure for high availability (five-nines uptime), data migrations with zero downtime, and other challenges in creating robust payment and billing services at scale.</p><p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://slack.engineering" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0EnU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F224c6d97-bfae-4772-8064-5152a110f96d_1600x572.png 424w, https://substackcdn.com/image/fetch/$s_!0EnU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F224c6d97-bfae-4772-8064-5152a110f96d_1600x572.png 848w, https://substackcdn.com/image/fetch/$s_!0EnU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F224c6d97-bfae-4772-8064-5152a110f96d_1600x572.png 1272w, https://substackcdn.com/image/fetch/$s_!0EnU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F224c6d97-bfae-4772-8064-5152a110f96d_1600x572.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0EnU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F224c6d97-bfae-4772-8064-5152a110f96d_1600x572.png" width="1456" height="521" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/224c6d97-bfae-4772-8064-5152a110f96d_1600x572.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:521,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:33888,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:&quot;https://slack.engineering&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/182873025?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F224c6d97-bfae-4772-8064-5152a110f96d_1600x572.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_!0EnU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F224c6d97-bfae-4772-8064-5152a110f96d_1600x572.png 424w, https://substackcdn.com/image/fetch/$s_!0EnU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F224c6d97-bfae-4772-8064-5152a110f96d_1600x572.png 848w, https://substackcdn.com/image/fetch/$s_!0EnU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F224c6d97-bfae-4772-8064-5152a110f96d_1600x572.png 1272w, https://substackcdn.com/image/fetch/$s_!0EnU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F224c6d97-bfae-4772-8064-5152a110f96d_1600x572.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 role="img" 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><title></title><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><h2><strong>Slack Engineering</strong></h2><blockquote><p><a href="https://slack.engineering">slack.engineering</a></p></blockquote><p>Slack&#8217;s tech blog offers insights into the backend of their popular messaging platform. Engineers at Slack share how they handle real-time messaging and event-driven architecture, scale out infrastructure to support millions of users, optimize performance, and ensure reliability. It&#8217;s full of practical lessons on building responsive, scalable web services.</p><p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://engineering.atspotify.com" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!icIy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0a6fd1b-358a-4d6c-9332-3ceeb36d5d30_3432x940.png 424w, https://substackcdn.com/image/fetch/$s_!icIy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0a6fd1b-358a-4d6c-9332-3ceeb36d5d30_3432x940.png 848w, https://substackcdn.com/image/fetch/$s_!icIy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0a6fd1b-358a-4d6c-9332-3ceeb36d5d30_3432x940.png 1272w, https://substackcdn.com/image/fetch/$s_!icIy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0a6fd1b-358a-4d6c-9332-3ceeb36d5d30_3432x940.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!icIy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0a6fd1b-358a-4d6c-9332-3ceeb36d5d30_3432x940.png" width="1456" height="399" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b0a6fd1b-358a-4d6c-9332-3ceeb36d5d30_3432x940.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:399,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:51035,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:&quot;https://engineering.atspotify.com&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/182873025?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0a6fd1b-358a-4d6c-9332-3ceeb36d5d30_3432x940.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_!icIy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0a6fd1b-358a-4d6c-9332-3ceeb36d5d30_3432x940.png 424w, https://substackcdn.com/image/fetch/$s_!icIy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0a6fd1b-358a-4d6c-9332-3ceeb36d5d30_3432x940.png 848w, https://substackcdn.com/image/fetch/$s_!icIy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0a6fd1b-358a-4d6c-9332-3ceeb36d5d30_3432x940.png 1272w, https://substackcdn.com/image/fetch/$s_!icIy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0a6fd1b-358a-4d6c-9332-3ceeb36d5d30_3432x940.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 role="img" 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><title></title><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><h2><strong>Spotify Engineering</strong></h2><blockquote><p><a href="https://engineering.atspotify.com">engineering.atspotify.com</a></p></blockquote><p>Spotify&#8217;s engineering blog covers how the world&#8217;s largest audio streaming service works under the hood. It includes stories about delivering music to hundreds of millions of users &#8211; from microservices and cloud architecture to data processing (for features like Spotify Wrapped), recommendation algorithms, and scaling storage and bandwidth for a global audience.</p><p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://airbnb.tech" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pZ5d!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb78ef4b1-195c-4064-8ed0-3b3e2e21eaed_978x450.jpeg 424w, https://substackcdn.com/image/fetch/$s_!pZ5d!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb78ef4b1-195c-4064-8ed0-3b3e2e21eaed_978x450.jpeg 848w, https://substackcdn.com/image/fetch/$s_!pZ5d!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb78ef4b1-195c-4064-8ed0-3b3e2e21eaed_978x450.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!pZ5d!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb78ef4b1-195c-4064-8ed0-3b3e2e21eaed_978x450.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pZ5d!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb78ef4b1-195c-4064-8ed0-3b3e2e21eaed_978x450.jpeg" width="978" height="450" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b78ef4b1-195c-4064-8ed0-3b3e2e21eaed_978x450.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:450,&quot;width&quot;:978,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:8484,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:&quot;https://airbnb.tech&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/182873025?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb78ef4b1-195c-4064-8ed0-3b3e2e21eaed_978x450.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!pZ5d!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb78ef4b1-195c-4064-8ed0-3b3e2e21eaed_978x450.jpeg 424w, https://substackcdn.com/image/fetch/$s_!pZ5d!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb78ef4b1-195c-4064-8ed0-3b3e2e21eaed_978x450.jpeg 848w, https://substackcdn.com/image/fetch/$s_!pZ5d!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb78ef4b1-195c-4064-8ed0-3b3e2e21eaed_978x450.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!pZ5d!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb78ef4b1-195c-4064-8ed0-3b3e2e21eaed_978x450.jpeg 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 role="img" 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><title></title><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><h2><strong>Airbnb Engineering &amp; Data Science</strong></h2><blockquote><p><a href="https://airbnb.tech">airbnb.tech</a></p></blockquote><p>Airbnb&#8217;s tech blog shares how they design the systems behind their home-sharing marketplace. It features articles on topics like service-oriented architecture, handling dynamic search and pricing at scale, data infrastructure (e.g. streaming and machine learning pipelines), and site reliability. It&#8217;s a great peek into scalable backend design for a two-sided online platform.</p><div><hr></div><p><strong>&#128233; Want more like this?</strong></p><p>Learning system design isn&#8217;t a one-week sprint.  It&#8217;s a long-term skill that grows with practice and good guidance.</p><p>No spam. No hype. Just things I wish someone had explained to me earlier.</p><p><strong>&#128073; Subscribe if you want the next post delivered straight to you.</strong></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://iam.slys.dev/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><p>Many other companies have similar engineering blogs - such as Meta&#8217;s Facebook Engineering and the Uber Engineering Blog - each offering a unique perspective. Don&#8217;t worry if some posts feel advanced; even a quick skim can introduce you to new concepts. Over time, you&#8217;ll start recognizing patterns and best practices that these big teams rely on. </p><blockquote><p><strong>Pro tip:</strong> if you encounter unfamiliar terms in a post, do a bit of quick research. That&#8217;s how I learned about things like <em>circuit breakers</em> and <em>CAP theorem</em> in the early days - one blog post at a time!</p></blockquote><h1>Personal Developer Blogs &#9997;&#65039;</h1><p>Company blogs are insightful, but they can be a bit formal. This is where personal developer blogs shine. Individual tech bloggers often share candid stories, practical how-to guides, and lessons learned from their own projects. It&#8217;s like sitting down with a friendly mentor who says, &#8220;<em>Hey, here&#8217;s something cool I figured out, maybe it&#8217;ll help you too</em>&#8221;. In fact, many developers start blogging specifically to document what they learn and to help others. These blogs tend to be very approachable for beginners. A few great ones to check out.</p><h2><strong>ByteByteGo Newsletter</strong></h2><blockquote><p><em>Alex Xu&#8217;s newsletter </em>| <a href="https://blog.bytebytego.com">link</a></p></blockquote><p>A weekly newsletter by <span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Alex Xu&quot;,&quot;id&quot;:22329494,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F10cd1afb-9a92-433e-bbf4-f726eb8ffdb3_375x375.jpeg&quot;,&quot;uuid&quot;:&quot;89857ab2-f803-498a-a234-0a82dddeaba5&quot;}" data-component-name="MentionToDOM"></span> (author of the <em>System Design Interview</em> books). It breaks down complex system design concepts into simple terms with diagrams. ByteByteGo covers everything from caching to database sharding, often using real-world case studies (like how popular systems are designed), making it a fantastic learning resource for system design and architecture.</p><h2><strong>The System Design Newsletter</strong></h2><blockquote><p><em>Neo Kim&#8217;s newsletter </em>| <em><a href="https://newsletter.systemdesign.one">link</a></em></p></blockquote><p><span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Neo Kim&quot;,&quot;id&quot;:135589200,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c103940f-0d8b-47e7-9a33-013202e17bb8_389x389.jpeg&quot;,&quot;uuid&quot;:&quot;96049b2b-82c3-4fb0-9465-3cab679fc129&quot;}" data-component-name="MentionToDOM"></span>&#8217;s Substack focuses on teaching system design in an approachable way. It&#8217;s known for beginner-friendly explanations of how things work (e.g. JWT authentication, load balancers) and fun case studies (&#8220;<em>How Uber handles 1M requests/sec</em>&#8221; etc.). Each post breaks down a topic or a famous system&#8217;s architecture into bite-sized lessons, perfect for engineers new to scalable system concepts.</p><h2><strong>Hello, World! System Design</strong></h2><blockquote><p><em>Rohit Lakhotia&#8217;s newsletter</em> | <a href="https://hw.glich.co">link</a></p></blockquote><p>This free weekly newsletter delivers one system design case study every Monday, often examining how big tech companies solve specific problems. Rohit Lakhotia&#8217;s content is very easy to digest, with plenty of diagrams and simple language. Topics range from &#8220;<em>How does URL shortening work?</em>&#8221; to deep dives like &#8220;<em>How Twitter handles millions of tweets</em>&#8221;, helping readers gradually build up system design knowledge through real examples.</p><h2><strong>AlgoMaster Newsletter</strong></h2><blockquote><p><em>Ashish Pratap Singh&#8217;s newsletter </em>| <a href="https://blog.algomaster.io">link</a></p></blockquote><p><span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Ashish Pratap Singh&quot;,&quot;id&quot;:83602743,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bec4e97e-29d0-4080-b529-db1f5fc4d1d2_1536x1536.jpeg&quot;,&quot;uuid&quot;:&quot;51a47b72-3dd7-44f4-8454-0189d06a0b9f&quot;}" data-component-name="MentionToDOM"></span>&#8217;s newsletter covers both coding and system design interview prep. It offers a mix of free and paid content, including lessons on scalable system concepts and interview questions (like designing a rate limiter or a chat system). It&#8217;s a handy resource for mastering fundamentals (caching, queueing, etc.) and for practicing the kind of system design problems you might face in tech interviews.</p><h2><strong>High Scalability</strong></h2><blockquote><p><em>Todd Hoff&#8217;s blog </em>| <a href="https://highscalability.com">link</a></p></blockquote><p>High Scalability is a long-running blog that compiles architecture lessons from real-world systems. Todd Hoff shares &#8220;<em>case studies</em>&#8221; of websites and applications that scaled to millions of users, analyzing the patterns and decisions that worked. Browsing the archives, you&#8217;ll find discussions of everything from how Facebook&#8217;s early architecture evolved to the design principles behind cloud services. It&#8217;s a treasure trove of scalability war stories and best practices.</p><h2><strong>Martin Fowler&#8217;s Blog</strong></h2><blockquote><p><em>Martin Fowler&#8217;s website </em>| <a href="https://www.martinfowler.com">link</a></p></blockquote><p>Martin Fowler, a renowned software architect, writes about software design paradigms that underpin robust systems. His blog isn&#8217;t exclusively about massive-scale systems, but it covers essential architectural topics like microservices, enterprise integration patterns, and evolutionary architecture. For anyone learning system design, Martin&#8217;s articles help build a strong foundation in software architecture fundamentals and thought processes.</p><h2><strong>System Design Classroom</strong></h2><blockquote><p><em>Raul Junco&#8217;s newsletter </em>| <a href="https://newsletter.systemdesignclassroom.com">link</a></p></blockquote><p><span class="mention-wrap" data-attrs="{&quot;name&quot;:&quot;Raul Junco&quot;,&quot;id&quot;:98661477,&quot;type&quot;:&quot;user&quot;,&quot;url&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/45a92f5e-1e2e-4dfa-9ff3-45fc5ad0c57e_612x612.png&quot;,&quot;uuid&quot;:&quot;7fe7249b-168f-44bf-b71f-b27ec0019e97&quot;}" data-component-name="MentionToDOM"></span>&#8217;s Substack is a fresh resource that helps developers &#8220;<em>build better software</em>&#8221; through system design insights. Each post tackles a specific concept or trade-off (for example, caching strategies, consistency vs. scalability, or pitfalls in distributed systems) in a practical way. The lessons are written in a friendly tone with concrete examples, making complex topics approachable for early-career engineers.</p><p>There are countless other personal blogs out there. Some notable mentions include <strong>Joel on Software</strong> (Joel Spolsky&#8217;s blog with great posts on software management and development), <strong>Scott Hanselman&#8217;s Blog </strong>(covering web development and productivity tips in a friendly tone), and community sites like <strong>DEV Community (Dev.to)</strong> or the <strong>freeCodeCamp blog</strong>, where lots of individual developers publish articles. The key is to find writers whose voice and topics resonate with you. When you do, follow their work. You&#8217;ll not only learn specific skills (like a new JavaScript trick or how to deploy an app) but also pick up good habits and mindsets by osmosis. And don&#8217;t be shy about interacting &#8211; many bloggers (myself included) love when readers leave comments or questions. It turns a blog into a two-way conversation, and you might just make some developer friends along the way!</p><div><hr></div><p>&#128257; <strong>Know someone who would find this useful?</strong></p><p>If you&#8217;ve ever felt overwhelmed while learning system design, you&#8217;re definitely not alone. Feel free to share this post with:</p><ul><li><p>a friend preparing for system design interviews</p></li><li><p>a junior developer who&#8217;s just getting started</p></li><li><p>or your past self from a few years ago &#128521;</p></li></ul><p><strong>Sometimes the right resource at the right time makes all the difference.</strong></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/how-to-learn-system-design-without?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://iam.slys.dev/p/how-to-learn-system-design-without?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h1>Must-Read Books &#128218;</h1><p>In this digital age, blogs and online code are readily available, so are books still worth it? Absolutely <strong>yes!</strong> Good books can organize and present knowledge in a way that builds your understanding step by step. They often go deeper into the <em>why</em> behind best practices and cover decades of wisdom that might be scattered across hundreds of blog posts. For a beginner (or any engineer, really), certain classic books are like a rite of passage - they shape how you think about writing software. Here are a few highly-recommended ones, each a gem in its own right!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://a.co/d/h75N77X" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4tZH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d4bf37b-04b0-4488-bad6-02f6b153e57d_1000x1499.jpeg 424w, https://substackcdn.com/image/fetch/$s_!4tZH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d4bf37b-04b0-4488-bad6-02f6b153e57d_1000x1499.jpeg 848w, https://substackcdn.com/image/fetch/$s_!4tZH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d4bf37b-04b0-4488-bad6-02f6b153e57d_1000x1499.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!4tZH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d4bf37b-04b0-4488-bad6-02f6b153e57d_1000x1499.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4tZH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d4bf37b-04b0-4488-bad6-02f6b153e57d_1000x1499.jpeg" width="1000" height="1499" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9d4bf37b-04b0-4488-bad6-02f6b153e57d_1000x1499.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1499,&quot;width&quot;:1000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:54472,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:&quot;https://a.co/d/h75N77X&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/182873025?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d4bf37b-04b0-4488-bad6-02f6b153e57d_1000x1499.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!4tZH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d4bf37b-04b0-4488-bad6-02f6b153e57d_1000x1499.jpeg 424w, https://substackcdn.com/image/fetch/$s_!4tZH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d4bf37b-04b0-4488-bad6-02f6b153e57d_1000x1499.jpeg 848w, https://substackcdn.com/image/fetch/$s_!4tZH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d4bf37b-04b0-4488-bad6-02f6b153e57d_1000x1499.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!4tZH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d4bf37b-04b0-4488-bad6-02f6b153e57d_1000x1499.jpeg 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 role="img" 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><title></title><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><h2><em>System Design Interview &#8211; An Insider&#8217;s Guide (Volume 1)</em> </h2><blockquote><p>by <strong>Alex Xu | </strong><a href="https://a.co/d/h75N77X">link</a></p></blockquote><p>A very popular book focused on preparing for system design interviews. It introduces a clear four-step framework for tackling design problems and walks through detailed examples (like designing a URL shortener, Twitter feed, etc.). Great for beginners &#8211; it teaches fundamentals of scalable design in a concise, easy-to-understand way, as if you&#8217;re solving interview questions with an expert mentor.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://a.co/d/cClthhA" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!n8nJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50519926-25fb-4a48-b1e3-b6266ee21fbe_1000x1429.jpeg 424w, https://substackcdn.com/image/fetch/$s_!n8nJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50519926-25fb-4a48-b1e3-b6266ee21fbe_1000x1429.jpeg 848w, https://substackcdn.com/image/fetch/$s_!n8nJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50519926-25fb-4a48-b1e3-b6266ee21fbe_1000x1429.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!n8nJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50519926-25fb-4a48-b1e3-b6266ee21fbe_1000x1429.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!n8nJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50519926-25fb-4a48-b1e3-b6266ee21fbe_1000x1429.jpeg" width="1000" height="1429" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/50519926-25fb-4a48-b1e3-b6266ee21fbe_1000x1429.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1429,&quot;width&quot;:1000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:48644,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:&quot;https://a.co/d/cClthhA&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/182873025?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50519926-25fb-4a48-b1e3-b6266ee21fbe_1000x1429.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!n8nJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50519926-25fb-4a48-b1e3-b6266ee21fbe_1000x1429.jpeg 424w, https://substackcdn.com/image/fetch/$s_!n8nJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50519926-25fb-4a48-b1e3-b6266ee21fbe_1000x1429.jpeg 848w, https://substackcdn.com/image/fetch/$s_!n8nJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50519926-25fb-4a48-b1e3-b6266ee21fbe_1000x1429.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!n8nJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50519926-25fb-4a48-b1e3-b6266ee21fbe_1000x1429.jpeg 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 role="img" 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><title></title><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><h2><em>System Design Interview &#8211; An Insider&#8217;s Guide (Volume 2)</em> </h2><blockquote><p>by <strong>Alex Xu &amp; Sahn Lam | </strong><a href="https://a.co/d/cClthhA">link</a></p></blockquote><p>The second volume builds on the first with all-new case studies and deeper dives. It covers more complex systems (such as designing YouTube, or a ridesharing system) and advanced topics like reliability, consistency trade-offs, and database sharding. Like Volume 1, it&#8217;s very approachable - perfect for developers who have basics down and want to level up with more practice scenarios and expert guidance.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://a.co/d/gHMT0vD" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!b5dR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb555a85-1283-44ab-9d61-13ce7745894f_1143x1500.jpeg 424w, https://substackcdn.com/image/fetch/$s_!b5dR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb555a85-1283-44ab-9d61-13ce7745894f_1143x1500.jpeg 848w, https://substackcdn.com/image/fetch/$s_!b5dR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb555a85-1283-44ab-9d61-13ce7745894f_1143x1500.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!b5dR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb555a85-1283-44ab-9d61-13ce7745894f_1143x1500.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!b5dR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb555a85-1283-44ab-9d61-13ce7745894f_1143x1500.jpeg" width="1143" height="1500" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/db555a85-1283-44ab-9d61-13ce7745894f_1143x1500.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1500,&quot;width&quot;:1143,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:230882,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:&quot;https://a.co/d/gHMT0vD&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/182873025?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb555a85-1283-44ab-9d61-13ce7745894f_1143x1500.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!b5dR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb555a85-1283-44ab-9d61-13ce7745894f_1143x1500.jpeg 424w, https://substackcdn.com/image/fetch/$s_!b5dR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb555a85-1283-44ab-9d61-13ce7745894f_1143x1500.jpeg 848w, https://substackcdn.com/image/fetch/$s_!b5dR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb555a85-1283-44ab-9d61-13ce7745894f_1143x1500.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!b5dR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb555a85-1283-44ab-9d61-13ce7745894f_1143x1500.jpeg 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 role="img" 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><title></title><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><h2><em>Designing Data-Intensive Applications</em></h2><blockquote><p>by <strong>Martin Kleppmann | </strong><a href="https://a.co/d/gHMT0vD">link</a></p></blockquote><p>A highly-acclaimed book that digs into the architecture of data systems. It explains how databases, distributed storage, and stream processing systems work under the hood, comparing different designs (SQL vs NoSQL, consistency models, batch vs streaming, etc.). This is more advanced in depth, but it&#8217;s essentially the <em>Bible</em> of distributed data systems &#8211; a must-read to truly understand scalability, fault tolerance, and data engineering in modern architectures.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://a.co/d/c0REeQl" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jLgT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79be8c25-5a0d-4356-97fe-57221209dd60_1143x1500.jpeg 424w, https://substackcdn.com/image/fetch/$s_!jLgT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79be8c25-5a0d-4356-97fe-57221209dd60_1143x1500.jpeg 848w, https://substackcdn.com/image/fetch/$s_!jLgT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79be8c25-5a0d-4356-97fe-57221209dd60_1143x1500.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!jLgT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79be8c25-5a0d-4356-97fe-57221209dd60_1143x1500.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jLgT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79be8c25-5a0d-4356-97fe-57221209dd60_1143x1500.jpeg" width="1143" height="1500" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/79be8c25-5a0d-4356-97fe-57221209dd60_1143x1500.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1500,&quot;width&quot;:1143,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:249765,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:&quot;https://a.co/d/c0REeQl&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/182873025?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79be8c25-5a0d-4356-97fe-57221209dd60_1143x1500.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!jLgT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79be8c25-5a0d-4356-97fe-57221209dd60_1143x1500.jpeg 424w, https://substackcdn.com/image/fetch/$s_!jLgT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79be8c25-5a0d-4356-97fe-57221209dd60_1143x1500.jpeg 848w, https://substackcdn.com/image/fetch/$s_!jLgT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79be8c25-5a0d-4356-97fe-57221209dd60_1143x1500.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!jLgT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79be8c25-5a0d-4356-97fe-57221209dd60_1143x1500.jpeg 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 role="img" 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><title></title><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><h2><em>Building Microservices</em></h2><blockquote><p>by <strong>Sam Newman | </strong><a href="https://a.co/d/c0REeQl">link</a></p></blockquote><p>An excellent introduction to the microservices style of architecture. Sam Newman covers why and how to split a system into services, and explores practical concerns like service communication, deployment, scaling, and monitoring. The book is full of real-world advice and anecdotes. It&#8217;s great for learners who want to understand service-oriented architecture and design systems that are modular, scalable, and easier to maintain over time.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://a.co/d/4CXJhJW" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!APEU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb12ad0b0-f142-4194-afa0-a909bbef1673_1250x1500.jpeg 424w, https://substackcdn.com/image/fetch/$s_!APEU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb12ad0b0-f142-4194-afa0-a909bbef1673_1250x1500.jpeg 848w, https://substackcdn.com/image/fetch/$s_!APEU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb12ad0b0-f142-4194-afa0-a909bbef1673_1250x1500.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!APEU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb12ad0b0-f142-4194-afa0-a909bbef1673_1250x1500.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!APEU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb12ad0b0-f142-4194-afa0-a909bbef1673_1250x1500.jpeg" width="1250" height="1500" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b12ad0b0-f142-4194-afa0-a909bbef1673_1250x1500.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1500,&quot;width&quot;:1250,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:114035,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:&quot;https://a.co/d/4CXJhJW&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/182873025?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb12ad0b0-f142-4194-afa0-a909bbef1673_1250x1500.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!APEU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb12ad0b0-f142-4194-afa0-a909bbef1673_1250x1500.jpeg 424w, https://substackcdn.com/image/fetch/$s_!APEU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb12ad0b0-f142-4194-afa0-a909bbef1673_1250x1500.jpeg 848w, https://substackcdn.com/image/fetch/$s_!APEU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb12ad0b0-f142-4194-afa0-a909bbef1673_1250x1500.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!APEU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb12ad0b0-f142-4194-afa0-a909bbef1673_1250x1500.jpeg 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 role="img" 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><title></title><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><h2><em>Release It! Design and Deploy Production-Ready Software</em></h2><blockquote><p>by <strong>Michael T. Nygard | </strong><a href="https://a.co/d/4CXJhJW">link</a></p></blockquote><p>A classic book focusing on the <strong>pragmatic</strong> aspects of system design &#8211; namely, making systems robust in real-life production. Michael Nygard introduces patterns for building resilient systems (circuit breakers, bulkheads, failsafes) and discusses the kinds of failure modes and outages that can happen at scale. Reading this will teach you how to design for stability and reliability, preparing you to avoid common pitfalls when your system is live and serving users.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://a.co/d/8zIXacC" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Whth!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05b095e2-9f39-46b4-b538-2b977e5b40a9_1143x1500.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Whth!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05b095e2-9f39-46b4-b538-2b977e5b40a9_1143x1500.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Whth!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05b095e2-9f39-46b4-b538-2b977e5b40a9_1143x1500.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Whth!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05b095e2-9f39-46b4-b538-2b977e5b40a9_1143x1500.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Whth!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05b095e2-9f39-46b4-b538-2b977e5b40a9_1143x1500.jpeg" width="1143" height="1500" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/05b095e2-9f39-46b4-b538-2b977e5b40a9_1143x1500.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1500,&quot;width&quot;:1143,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:187223,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:&quot;https://a.co/d/8zIXacC&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/182873025?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05b095e2-9f39-46b4-b538-2b977e5b40a9_1143x1500.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Whth!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05b095e2-9f39-46b4-b538-2b977e5b40a9_1143x1500.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Whth!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05b095e2-9f39-46b4-b538-2b977e5b40a9_1143x1500.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Whth!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05b095e2-9f39-46b4-b538-2b977e5b40a9_1143x1500.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Whth!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05b095e2-9f39-46b4-b538-2b977e5b40a9_1143x1500.jpeg 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 role="img" 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><title></title><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><h2><em>Fundamentals of Software Architecture</em></h2><blockquote><p>by <strong>Mark Richards &amp; Neal Ford | </strong><a href="https://a.co/d/8zIXacC">link</a></p></blockquote><p>A comprehensive guide to software architecture principles. It&#8217;s not limited to web scale systems - it covers a broad range of architectural styles (layered, microservices, event-driven, etc.), component design, and quality attributes (like scalability, performance, security). For someone new to architecture, this book builds a solid base of knowledge, teaching you how to think like an architect and evaluate design trade-offs before diving into specific implementations.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://a.co/d/8b9r7m7" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Xv6p!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b98b3f6-ab53-4e9b-9a8a-9cc82ec85d3e_1000x1500.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Xv6p!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b98b3f6-ab53-4e9b-9a8a-9cc82ec85d3e_1000x1500.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Xv6p!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b98b3f6-ab53-4e9b-9a8a-9cc82ec85d3e_1000x1500.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Xv6p!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b98b3f6-ab53-4e9b-9a8a-9cc82ec85d3e_1000x1500.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Xv6p!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b98b3f6-ab53-4e9b-9a8a-9cc82ec85d3e_1000x1500.jpeg" width="1000" height="1500" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8b98b3f6-ab53-4e9b-9a8a-9cc82ec85d3e_1000x1500.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1500,&quot;width&quot;:1000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:81554,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:&quot;https://a.co/d/8b9r7m7&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/182873025?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b98b3f6-ab53-4e9b-9a8a-9cc82ec85d3e_1000x1500.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Xv6p!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b98b3f6-ab53-4e9b-9a8a-9cc82ec85d3e_1000x1500.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Xv6p!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b98b3f6-ab53-4e9b-9a8a-9cc82ec85d3e_1000x1500.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Xv6p!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b98b3f6-ab53-4e9b-9a8a-9cc82ec85d3e_1000x1500.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Xv6p!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8b98b3f6-ab53-4e9b-9a8a-9cc82ec85d3e_1000x1500.jpeg 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 role="img" 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><title></title><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><h2><em>Understanding Distributed Systems</em></h2><blockquote><p>by <strong>Roberto Vitillo | </strong><a href="https://a.co/d/8b9r7m7">link</a><strong> </strong></p></blockquote><p>A concise and beginner-friendly book that demystifies distributed systems. Roberto Vitillo explains core concepts such as network communication, replication, partitioning, and consensus in plain language with simple examples. It&#8217;s a shorter read that doesn&#8217;t assume prior knowledge - perfect for junior engineers who want to grasp how distributed systems work (and why they can be tricky) in order to design better software systems.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://a.co/d/4cQifVG" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6znJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9373d7fa-4349-4f87-ba51-a57d1082890c_800x1053.jpeg 424w, https://substackcdn.com/image/fetch/$s_!6znJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9373d7fa-4349-4f87-ba51-a57d1082890c_800x1053.jpeg 848w, https://substackcdn.com/image/fetch/$s_!6znJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9373d7fa-4349-4f87-ba51-a57d1082890c_800x1053.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!6znJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9373d7fa-4349-4f87-ba51-a57d1082890c_800x1053.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6znJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9373d7fa-4349-4f87-ba51-a57d1082890c_800x1053.jpeg" width="800" height="1053" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9373d7fa-4349-4f87-ba51-a57d1082890c_800x1053.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1053,&quot;width&quot;:800,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:82305,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:&quot;https://a.co/d/4cQifVG&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/182873025?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9373d7fa-4349-4f87-ba51-a57d1082890c_800x1053.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6znJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9373d7fa-4349-4f87-ba51-a57d1082890c_800x1053.jpeg 424w, https://substackcdn.com/image/fetch/$s_!6znJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9373d7fa-4349-4f87-ba51-a57d1082890c_800x1053.jpeg 848w, https://substackcdn.com/image/fetch/$s_!6znJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9373d7fa-4349-4f87-ba51-a57d1082890c_800x1053.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!6znJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9373d7fa-4349-4f87-ba51-a57d1082890c_800x1053.jpeg 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 role="img" 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><title></title><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><h2><em>The Art of Scalability</em></h2><blockquote><p>by <strong>Martin L. Abbott &amp; Michael T. Fisher | </strong><a href="https://a.co/d/4cQifVG">link</a></p></blockquote><p>Written by two former web executives, this book takes a holistic view of scalability. It covers technical strategies for scaling (architecture patterns, database scaling, caching, etc.) <em>and</em> touches on the people and process side (like organizing engineering teams for scale). The authors present a framework called <em>the Scale Cube</em> for thinking about growth. It&#8217;s an insightful read for learning to design systems that can grow from a small app to an enterprise-scale platform, while avoiding common scaling bottlenecks.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://a.co/d/9UerWYt" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!E1KO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d11e65c-2d29-4dfa-9765-da2a2af4f98c_1143x1500.jpeg 424w, https://substackcdn.com/image/fetch/$s_!E1KO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d11e65c-2d29-4dfa-9765-da2a2af4f98c_1143x1500.jpeg 848w, https://substackcdn.com/image/fetch/$s_!E1KO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d11e65c-2d29-4dfa-9765-da2a2af4f98c_1143x1500.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!E1KO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d11e65c-2d29-4dfa-9765-da2a2af4f98c_1143x1500.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!E1KO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d11e65c-2d29-4dfa-9765-da2a2af4f98c_1143x1500.jpeg" width="1143" height="1500" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6d11e65c-2d29-4dfa-9765-da2a2af4f98c_1143x1500.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1500,&quot;width&quot;:1143,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:181326,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:&quot;https://a.co/d/9UerWYt&quot;,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/182873025?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d11e65c-2d29-4dfa-9765-da2a2af4f98c_1143x1500.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!E1KO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d11e65c-2d29-4dfa-9765-da2a2af4f98c_1143x1500.jpeg 424w, https://substackcdn.com/image/fetch/$s_!E1KO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d11e65c-2d29-4dfa-9765-da2a2af4f98c_1143x1500.jpeg 848w, https://substackcdn.com/image/fetch/$s_!E1KO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d11e65c-2d29-4dfa-9765-da2a2af4f98c_1143x1500.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!E1KO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d11e65c-2d29-4dfa-9765-da2a2af4f98c_1143x1500.jpeg 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 role="img" 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><title></title><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><h2><em>Site Reliability Engineering: How Google Runs Production Systems</em></h2><blockquote><p>by <strong>Jennifer Petoff</strong>, <strong>Betsy Beyer</strong>, <strong>Chris Jones</strong>, <strong>Niall Richard Murphy | </strong><a href="https://a.co/d/9UerWYt">link</a></p></blockquote><p>This book, authored by Google&#8217;s SREs, is all about operating and sustaining large systems reliably. It&#8217;s essentially a compilation of essays on topics like building scalable monitoring, handling on-call and incidents, automation, and engineering for resiliency (at Google scale). While it&#8217;s more about running systems, there are plenty of design insights - after all, <em>&#8220;hope is not a strategy&#8221;</em> when designing for reliability. Reading it will broaden your perspective on designing systems that not only scale, but stay available and maintainable in real-world conditions.</p><p>Of course, there are other fantastic books depending on your interests: <em>Introduction to Algorithms</em> (Cormen et al.) if you&#8217;re into computer science theory, <em>Don&#8217;t Make Me Think</em> (Steve Krug) if you want to learn about usability and user experience, <em>Head First Design Patterns</em> for an interactive way to learn design patterns, and more. But the three above are almost universally praised in the developer community for building solid foundations. If you can, I highly recommend picking up at least one of them. Try reading a chapter after you&#8217;ve done a bit of coding for the day - you&#8217;ll often find something in the book that you can immediately apply to your own code, which helps reinforce the lesson. Plus, nothing beats the feel of flipping through a book and realizing you&#8217;ve understood concepts that seemed gibberish a month ago. &#128214;&#127881;</p><h1>Conclusion &#127775;</h1><p>Piecing together the software development puzzle takes time, but with these resources, you&#8217;ve got a clear picture to work towards. Each company blog post you read, each personal blog story and each chapter in a book adds another piece to your understanding. Over time, things that once seemed mystifying will click into place. You&#8217;ll catch yourself saying, &#8220;<em>Oh, I remember reading about this!</em>&#8221; and suddenly using that knowledge in your own project. That&#8217;s one of the most rewarding feelings as a new developer.</p><p>Remember, everyone&#8217;s journey is a bit different. You might prefer reading a blog over a book, or tinkering with code over reading about code - and that&#8217;s okay! Use the mix of resources that <em>excites you the most</em>. The fact that you&#8217;re proactively learning from blogs, open-source, and books already sets you apart. As Steve McConnell noted, the average programmer reads less than one technical book per year - but here you are, eager to learn and improve. Kudos to you. &#128588;</p><p>Finally, stay curious and don&#8217;t be afraid to ask for help. The developer community is full of people who were once beginners and are happy to pay it forward. Whether it&#8217;s commenting on a blog, joining a forum, or asking a question on Stack Overflow, you&#8217;ll find that most folks are welcoming and supportive. I <strong>love</strong> engaging with readers on this blog, so if you have questions or want to share your own favorite resource, drop a comment below. Let&#8217;s learn together!</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/how-to-learn-system-design-without/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/how-to-learn-system-design-without/comments"><span>Leave a comment</span></a></p><p><strong>Happy coding, and enjoy the journey!</strong> </p><p>The pieces will come together before you know it. &#129513;&#10024;</p>]]></content:encoded></item><item><title><![CDATA[Why databases get split — sharding, partitioning, and replication without fear]]></title><description><![CDATA[System design fundamentals]]></description><link>https://iam.slys.dev/p/why-databases-get-split-sharding</link><guid isPermaLink="false">https://iam.slys.dev/p/why-databases-get-split-sharding</guid><dc:creator><![CDATA[Jakub Slys 🤖]]></dc:creator><pubDate>Mon, 22 Dec 2025 21:10:02 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!GZbt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6c35ce0-783f-423e-85a8-c22b7a74b87c_1536x1024.heic" 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_!GZbt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6c35ce0-783f-423e-85a8-c22b7a74b87c_1536x1024.heic" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GZbt!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6c35ce0-783f-423e-85a8-c22b7a74b87c_1536x1024.heic 424w, https://substackcdn.com/image/fetch/$s_!GZbt!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6c35ce0-783f-423e-85a8-c22b7a74b87c_1536x1024.heic 848w, https://substackcdn.com/image/fetch/$s_!GZbt!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6c35ce0-783f-423e-85a8-c22b7a74b87c_1536x1024.heic 1272w, https://substackcdn.com/image/fetch/$s_!GZbt!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6c35ce0-783f-423e-85a8-c22b7a74b87c_1536x1024.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GZbt!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6c35ce0-783f-423e-85a8-c22b7a74b87c_1536x1024.heic" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e6c35ce0-783f-423e-85a8-c22b7a74b87c_1536x1024.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:149915,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176729823?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6c35ce0-783f-423e-85a8-c22b7a74b87c_1536x1024.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!GZbt!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6c35ce0-783f-423e-85a8-c22b7a74b87c_1536x1024.heic 424w, https://substackcdn.com/image/fetch/$s_!GZbt!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6c35ce0-783f-423e-85a8-c22b7a74b87c_1536x1024.heic 848w, https://substackcdn.com/image/fetch/$s_!GZbt!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6c35ce0-783f-423e-85a8-c22b7a74b87c_1536x1024.heic 1272w, https://substackcdn.com/image/fetch/$s_!GZbt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6c35ce0-783f-423e-85a8-c22b7a74b87c_1536x1024.heic 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 role="img" 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><title></title><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><blockquote><p>Imagine keeping all your clothes in one drawer.<br>At first, it&#8217;s fine - a few shirts, some jeans.<br>But then seasons change, new clothes arrive, and suddenly the drawer won&#8217;t close.<br>You try to push harder. Nothing helps.</p><p>That&#8217;s what happens when a system grows - and your single database can no longer fit everything inside. It&#8217;s time to split the drawer.</p></blockquote><p>In tech terms, that overstuffed drawer is like a monolithic database. As your application grows, you eventually reach a point where no matter how much you try to squeeze in (or how powerful you make the server), <strong>one database just isn&#8217;t enough</strong>. Splitting a database can sound scary, but it&#8217;s a natural evolution when your data outgrows a single container. In this post, we&#8217;ll explore why and how databases get &#8220;<em>split</em>&#8221; through <strong>partitioning</strong>, <strong>sharding</strong>, and <strong>replication</strong> - demystifying these concepts so they&#8217;re not so fearsome after all.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!BTor!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31ac6a07-c1df-4e1b-ae64-2c2da8e8c563_2161x1729.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!BTor!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31ac6a07-c1df-4e1b-ae64-2c2da8e8c563_2161x1729.heic 424w, https://substackcdn.com/image/fetch/$s_!BTor!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31ac6a07-c1df-4e1b-ae64-2c2da8e8c563_2161x1729.heic 848w, https://substackcdn.com/image/fetch/$s_!BTor!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31ac6a07-c1df-4e1b-ae64-2c2da8e8c563_2161x1729.heic 1272w, https://substackcdn.com/image/fetch/$s_!BTor!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31ac6a07-c1df-4e1b-ae64-2c2da8e8c563_2161x1729.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!BTor!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31ac6a07-c1df-4e1b-ae64-2c2da8e8c563_2161x1729.heic" width="725.484375" height="580.4871544471154" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/31ac6a07-c1df-4e1b-ae64-2c2da8e8c563_2161x1729.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:1165,&quot;width&quot;:1456,&quot;resizeWidth&quot;:725.484375,&quot;bytes&quot;:119567,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176729823?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31ac6a07-c1df-4e1b-ae64-2c2da8e8c563_2161x1729.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!BTor!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31ac6a07-c1df-4e1b-ae64-2c2da8e8c563_2161x1729.heic 424w, https://substackcdn.com/image/fetch/$s_!BTor!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31ac6a07-c1df-4e1b-ae64-2c2da8e8c563_2161x1729.heic 848w, https://substackcdn.com/image/fetch/$s_!BTor!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31ac6a07-c1df-4e1b-ae64-2c2da8e8c563_2161x1729.heic 1272w, https://substackcdn.com/image/fetch/$s_!BTor!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F31ac6a07-c1df-4e1b-ae64-2c2da8e8c563_2161x1729.heic 1456w" sizes="100vw"></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 role="img" 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><title></title><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><h1>&#129513; When one database isn&#8217;t enough</h1><p>At a small scale, a single database can handle all your application&#8217;s data and queries easily. But as the application (and its user base) grows, problems start to appear:</p><ul><li><p><strong>More users &#8594; more data:</strong> The database has to store more and more records, and operations on a single giant dataset inevitably slow down.</p></li></ul><ul><li><p><strong>More activity &#8594; more load:</strong> Heavier read/write traffic can overwhelm the database&#8217;s CPU, memory, or disk throughput.</p></li><li><p><strong>Maintenance overhead:</strong> Backups take longer, indexes grow larger, and routine queries or reports start dragging due to the sheer volume of data.</p></li></ul><p>You can try to <strong>scale vertically</strong> (add more CPU, RAM, or a faster disk to the database server) to get relief. This helps for a while, but only up to a point. Every system reaches a stage where adding hardware is like pouring water into a full glass - it just spills over. In other words, a single machine will eventually hit a physical limit, no matter how beefy it is.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a> Beyond that, continuing to push growth on one database is impractical (or outright impossible) - it&#8217;s time to <strong>scale out</strong> by splitting.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qb4b!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faeab9475-9778-43a7-a937-ea52b5bb7d7f_2877x2171.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qb4b!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faeab9475-9778-43a7-a937-ea52b5bb7d7f_2877x2171.heic 424w, https://substackcdn.com/image/fetch/$s_!qb4b!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faeab9475-9778-43a7-a937-ea52b5bb7d7f_2877x2171.heic 848w, https://substackcdn.com/image/fetch/$s_!qb4b!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faeab9475-9778-43a7-a937-ea52b5bb7d7f_2877x2171.heic 1272w, https://substackcdn.com/image/fetch/$s_!qb4b!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faeab9475-9778-43a7-a937-ea52b5bb7d7f_2877x2171.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qb4b!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faeab9475-9778-43a7-a937-ea52b5bb7d7f_2877x2171.heic" width="1200" height="905.7692307692307" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/aeab9475-9778-43a7-a937-ea52b5bb7d7f_2877x2171.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1099,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:128871,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176729823?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faeab9475-9778-43a7-a937-ea52b5bb7d7f_2877x2171.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!qb4b!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faeab9475-9778-43a7-a937-ea52b5bb7d7f_2877x2171.heic 424w, https://substackcdn.com/image/fetch/$s_!qb4b!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faeab9475-9778-43a7-a937-ea52b5bb7d7f_2877x2171.heic 848w, https://substackcdn.com/image/fetch/$s_!qb4b!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faeab9475-9778-43a7-a937-ea52b5bb7d7f_2877x2171.heic 1272w, https://substackcdn.com/image/fetch/$s_!qb4b!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faeab9475-9778-43a7-a937-ea52b5bb7d7f_2877x2171.heic 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 role="img" 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><title></title><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><h1>&#9881;&#65039; Three survival strategies &#8212; partitioning, sharding, and replication</h1><p>So, how do we &#8220;<em>split the drawer</em>&#8221; in practice? There are three fundamental strategies (often used together) to divide and conquer a growing data set. The table below gives a quick overview:</p><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/2wxZR/2/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b6b850e7-cf23-4bc2-9797-6818093646a1_1220x558.png&quot;,&quot;thumbnail_url_full&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/54da5c71-d8e2-42f9-a51c-7fc33e435446_1220x628.png&quot;,&quot;height&quot;:240,&quot;title&quot;:&quot;Three survival strategies&quot;,&quot;description&quot;:&quot;&quot;}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/2wxZR/2/" width="730" height="240" frameborder="0" scrolling="no"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><p><em>Partitioning organizes. Sharding scales. Replication protects.</em> Each addresses a different problem of scale. Let&#8217;s dive into each one and see how they work.</p><div><hr></div><p>&#128257; <strong>This is usually where things start to click.</strong></p><p>If this made databases feel less scary, it might help someone else too.  </p><p>Share this article with someone who&#8217;s afraid of scaling.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/why-databases-get-split-sharding?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/why-databases-get-split-sharding?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h1>&#129518; Partitioning &#8212; organizing data so it makes sense</h1><p><strong>Partitioning</strong> means dividing one big dataset into smaller, more manageable chunks. Instead of one monolithic table or collection containing everything, you break it into pieces that are easier to work with. The goal is to group related data together and separate unrelated data, which improves clarity and performance.</p><p>There are two common forms of partitioning.</p><p><strong>Vertical partitioning.</strong> Splitting data by category or feature. For example, an e-commerce application might keep user profiles in one set of tables and order history in another. In relational terms, this could mean putting different functional domains in different tables or databases (or breaking a very wide table into multiple tables by columns). Each vertical partition holds a subset of the columns/fields. Frequently accessed fields might live in one partition, while rarely used or very sensitive fields live in another. This way, each partition is focused on a specific subset of the data (often reflecting a particular feature or usage pattern).</p><p><strong>Horizontal partitioning. </strong>Splitting data by rows, usually based on some key or value range. For example, you could partition a customer table so that customers with last names A&#8211;M are in one partition and N&#8211;Z in another, or split a huge log table by month. Each horizontal partition contains a subset of the rows but has the same schema (columns) as the others. Often, horizontal partitioning is implemented as &#8220;<em>ranges</em>&#8221; (e.g. IDs 1-1,000,000 in one partition, 1,000,001-2,000,000 in the next) or lists (explicit groups, like region codes or alphabetical ranges).</p><p><strong>Why partition at all?</strong> Because each partition is smaller than the whole dataset, queries and index lookups can be faster - they only scan a relevant subset of data rather than everything. For example, if you partition a log table by date, a query for &#8220;<em>last month&#8217;s logs</em>&#8221; only needs to read the partition for that month, not the entire year&#8217;s data.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a> Smaller chunks of data also mean <strong>smaller indexes</strong> and working sets, which can fit into memory more easily and speed up performance. Partitioning can even help with caching: if one subset of data is &#8220;<em>hot</em>&#8221; (frequently accessed) and others are &#8220;<em>cold</em>&#8221;, you could keep the hot partition in memory or on a fast disk, and the cold partitions on cheaper storage. For instance, stable, rarely-changing data (say, product descriptions) might be stored in one partition that you cache aggressively, while dynamic data (stock levels) is in another partition that gets updated regularly.</p><p>Another benefit is manageability: it&#8217;s easier to <strong>maintain and back up</strong> a 100 GB partition than a single 1 TB monolith. You can backup or restore one segment at a time, or even take one partition offline without affecting others, etc. Partitioning can also improve availability by isolating faults - if one partition (on one server) crashes, the others can still function, so it&#8217;s not a total outage.</p><p>In short, partitioning is like organizing your wardrobe. Instead of one chaotic closet where everything&#8217;s piled up, you have separate sections: shirts here, jackets there, pants in another. Each section is easier to search through on its own. Likewise, a partitioned database is <strong>neater and more efficient</strong>: related data stays together, and queries can target just the right &#8220;<em>section</em>&#8221; instead of rifling through everything.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!lgUy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45dca50a-98f5-484c-92ef-fae34f1d8dba_1806x1056.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lgUy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45dca50a-98f5-484c-92ef-fae34f1d8dba_1806x1056.heic 424w, https://substackcdn.com/image/fetch/$s_!lgUy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45dca50a-98f5-484c-92ef-fae34f1d8dba_1806x1056.heic 848w, https://substackcdn.com/image/fetch/$s_!lgUy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45dca50a-98f5-484c-92ef-fae34f1d8dba_1806x1056.heic 1272w, https://substackcdn.com/image/fetch/$s_!lgUy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45dca50a-98f5-484c-92ef-fae34f1d8dba_1806x1056.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!lgUy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45dca50a-98f5-484c-92ef-fae34f1d8dba_1806x1056.heic" width="1456" height="851" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/45dca50a-98f5-484c-92ef-fae34f1d8dba_1806x1056.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:851,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:72450,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176729823?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45dca50a-98f5-484c-92ef-fae34f1d8dba_1806x1056.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!lgUy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45dca50a-98f5-484c-92ef-fae34f1d8dba_1806x1056.heic 424w, https://substackcdn.com/image/fetch/$s_!lgUy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45dca50a-98f5-484c-92ef-fae34f1d8dba_1806x1056.heic 848w, https://substackcdn.com/image/fetch/$s_!lgUy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45dca50a-98f5-484c-92ef-fae34f1d8dba_1806x1056.heic 1272w, https://substackcdn.com/image/fetch/$s_!lgUy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45dca50a-98f5-484c-92ef-fae34f1d8dba_1806x1056.heic 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 role="img" 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><title></title><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><h1>&#127757; Sharding &#8212; when you need more than one database</h1><p>While partitioning often refers to splitting data within a single database system, <strong>sharding</strong> takes it one step further: it spreads the data across <em>multiple</em> database servers. In fact, sharding is basically horizontal partitioning, but done <strong>across servers or instances</strong>, not just within one. Each shard is an independent database holding a slice of the overall data, and all shards share the same schema structure (they have the same tables/collections, just different rows).</p><p>Sharding is a classic approach to <strong>horizontal scaling</strong>. Instead of pushing the limits of one big machine, you use several machines in parallel - each handling only a portion of the workload. For example, imagine a service with millions of users. Rather than keeping all user records in one database server, you could split users between two shards: say, User IDs 1 - 1,000,000 on <strong>Shard A</strong> (Server A) and User IDs 1,000,001 - 2,000,000 on <strong>Shard B</strong> (Server B). If a user with ID 500,000 logs in, the application knows to check Shard A; if ID 1,500,000, it goes to Shard B. The key that determines which shard to go to (here, the user ID) is called the <strong>shard key</strong>. The application (or a routing service) uses the shard key to direct each query to the right shard.</p><p>Sharding can also be based on other schemes. For instance, a social media platform might shard by geography: users from North America on one database instance, Europe on another, Asia on a third, etc. This way each shard handles a region&#8217;s users, potentially reducing latency by keeping data geographically close to its users. The important point is that <strong>each shard contains a distinct subset of the data</strong> and collectively the shards make up the entire dataset.</p><p>How do we decide <em>who gets what</em> in a sharded setup? There are a few common sharding strategies.</p><p><strong>Range-based sharding.</strong> Each shard owns a continuous range of data values. For example, shard 1 has IDs from 1-1M, shard 2 has 1M-2M, etc., or one shard has &#8220;<em>A-G</em>&#8221; customers, the next has &#8220;<em>H-N</em>,&#8221; and so on. This approach is easy to understand and to query when you know a specific value&#8217;s range (e.g. to find all &#8220;<em>A-G</em>&#8221; customers, you only hit that one shard). However, range sharding can lead to <strong>uneven load</strong> if the data isn&#8217;t uniform. In the alphabet example, one shard might end up with a ton of data (if many last names start with S, for instance) and become a hot spot. Using the first letter of a name would cause an unbalanced distribution because some letters are far more common than others. In such cases, the shard holding &#8220;<em>S</em>&#8221; or &#8220;<em>M</em>&#8221; might struggle while others sit mostly idle.</p><p><strong>Hash-based sharding.</strong> To avoid the imbalance of simple ranges, many systems use a hash function on the key. The hash (perhaps modded into a number of buckets) determines which shard the data goes to. This tends to distribute data evenly in a pseudo-random way (so &#8220;<em>Alice</em>&#8221; might go to Shard 1 and &#8220;<em>Zelda</em>&#8221; to Shard 3, regardless of alphabetical order, if their hashed IDs differ). The big advantage is avoiding any one very heavy shard - no obvious pattern means load is spread out. The trade-off is that <strong>related items might not live together</strong>, and queries that need a range of data (say, all users in California, or IDs between 1000 and 2000) won&#8217;t be neatly contained in one shard. Cross-shard queries become more complex, since you might have to ask every shard and then combine results. In other words, hash-based sharding sacrifices some query flexibility for balance.</p><p><strong>Geographic or domain-based sharding.</strong> This strategy uses a natural segmentation of your user base or data domain. For example, you shard by region (as mentioned) or by customer type (free vs. premium customers on different shards), etc. The benefit is often lower latency and localized failures - each shard can be placed physically closer to its users and handle their specific load. It can also simplify compliance (e.g., European user data stays on an EU server). However, if one category has a lot more users or activity than another, you can still end up with an imbalanced situation. You also have to deal with <em>global</em> queries (aggregating data from all shards) in application logic, since the database no longer has everything in one place.</p><p>Sharding is like opening new branches of a library. Imagine a single central library that&#8217;s become too crowded - people wait in long lines, it&#8217;s slow to find books, and it&#8217;s running out of space. The solution: open one branch on the north side of town and another on the south side. Now each branch (shard) serves its local neighborhood, storing copies of books relevant to that area or portion of the catalog, but no one branch has to hold <em>all</em> the books. If you know which branch has the book you need, you go straight there. Similarly, with database sharding, the application routes each query to the correct shard that holds that piece of data, instead of every query hitting one monolithic database.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pGPd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe21ff3c9-7ada-4d1e-a9fb-212ad1fb84fc_2453x1241.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pGPd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe21ff3c9-7ada-4d1e-a9fb-212ad1fb84fc_2453x1241.heic 424w, https://substackcdn.com/image/fetch/$s_!pGPd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe21ff3c9-7ada-4d1e-a9fb-212ad1fb84fc_2453x1241.heic 848w, https://substackcdn.com/image/fetch/$s_!pGPd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe21ff3c9-7ada-4d1e-a9fb-212ad1fb84fc_2453x1241.heic 1272w, https://substackcdn.com/image/fetch/$s_!pGPd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe21ff3c9-7ada-4d1e-a9fb-212ad1fb84fc_2453x1241.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pGPd!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe21ff3c9-7ada-4d1e-a9fb-212ad1fb84fc_2453x1241.heic" width="1200" height="607.4175824175824" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e21ff3c9-7ada-4d1e-a9fb-212ad1fb84fc_2453x1241.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:737,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:87686,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176729823?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe21ff3c9-7ada-4d1e-a9fb-212ad1fb84fc_2453x1241.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!pGPd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe21ff3c9-7ada-4d1e-a9fb-212ad1fb84fc_2453x1241.heic 424w, https://substackcdn.com/image/fetch/$s_!pGPd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe21ff3c9-7ada-4d1e-a9fb-212ad1fb84fc_2453x1241.heic 848w, https://substackcdn.com/image/fetch/$s_!pGPd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe21ff3c9-7ada-4d1e-a9fb-212ad1fb84fc_2453x1241.heic 1272w, https://substackcdn.com/image/fetch/$s_!pGPd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe21ff3c9-7ada-4d1e-a9fb-212ad1fb84fc_2453x1241.heic 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 role="img" 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><title></title><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><blockquote><p><strong>Insight:</strong> By scaling horizontally with shards, we <strong>trade simplicity for capacity and resilience</strong>. A sharded system is more complex to manage than a single database (you have multiple moving parts and distributed logic), but it can handle vastly more data and traffic. There&#8217;s no single monster server carrying the entire load, and if one shard server goes down, it only affects a subset of users/data rather than bringing everything down. In short, <em>sharding sacrifices the convenience of one-stop querying in order to gain virtually unlimited scalability</em>.</p></blockquote><h1>&#128257; Replication &#8212; when safety matters more than speed</h1><p>Partitioning and sharding split <em>different</em> data across spaces - but <strong>replication</strong> is about duplicating the <em>same</em> data across multiple places. When you replicate a database, you make one or more copies of it on separate nodes. These copies stay synchronized (often with a small delay) by copying over every write/update. Why do this? <strong>Redundancy</strong>. If one database instance crashes, or if you simply need extra read capacity, having replicas of the data keeps the system running without interruption.</p><p>In formal terms, <em>database replication</em> is the process of copying and maintaining database objects (like tables, records, whole states) across multiple nodes to ensure <strong>data redundancy, durability, availability, and often better performance</strong>.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a> Instead of a single point of failure, you have backups that can step in, and instead of one server handling all reads, you can spread reads across replicas. There are a couple of common replication setups.</p><p><strong>Master&#8211;slave (primary&#8211;replica) replication.</strong> In this classic model, one node is designated the <strong>primary</strong> (master) server, which handles all the writes. One or more other nodes act as <strong>read replicas</strong> (slaves) that continuously copy the primary&#8217;s data changes. All writes go to the master, which ensures there&#8217;s a single source of truth for updates (no update conflicts). The replicas subscribe to the master&#8217;s change log and apply those changes to stay up-to-date. Reads, however, can be distributed: your application can query the replicas for read-only operations, thereby offloading work from the primary.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a> For example, a popular website might use one primary database for handling user transactions, and 5 replica databases to serve various read-heavy features (like search or analytics queries) in parallel. This <strong>improves read scalability</strong> without compromising write consistency (since writes all still funnel through the single master). If the master server fails, one of the replicas can be promoted to master - this is a failover mechanism that provides high availability. The drawback to master-slave replication is that the master can still be a bottleneck for write-heavy workloads (all writes have to go to one place) and a single point of failure for writes (during normal operation). Also, replicas are usually slightly behind the master in time - if replication is asynchronous, a recent write might not yet have reached the replica when a read is done, meaning replicas can serve <strong>stale data</strong> (more on that trade-off shortly).</p><p><strong>Multi-master replication.</strong> This is a more decentralized approach where <strong>multiple nodes can accept writes</strong> and replicate to each other. In a multi-master setup, you could have, say, two or three primary nodes (perhaps in different data centers) all processing user updates, and they exchange their changes with one another to converge on the same data state. The big advantage is there&#8217;s no single choke point for writing &#8211; you can handle writes in parallel at multiple locations, and if one node fails, the others are still live (improving availability). However, multi-master replication is <strong>considerably more complex</strong>. If two masters change the same piece of data at the same time (a write conflict), the system needs a conflict resolution strategy (last write wins? merge changes? custom logic?). Ensuring consistency is tricky - you often end up with <strong>eventual consistency</strong> (updates will reach all nodes, but for a short time different nodes might have different data). Multi-master systems must deal with issues like write conflicts, network partitions, and heavier coordination overhead. This approach is used in certain distributed databases and multi-region deployments (so each region can accept local writes), but it requires careful design.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xkoj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F392819f1-65f2-4637-9bbb-fb8b9d42210c_2129x932.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xkoj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F392819f1-65f2-4637-9bbb-fb8b9d42210c_2129x932.heic 424w, https://substackcdn.com/image/fetch/$s_!xkoj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F392819f1-65f2-4637-9bbb-fb8b9d42210c_2129x932.heic 848w, https://substackcdn.com/image/fetch/$s_!xkoj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F392819f1-65f2-4637-9bbb-fb8b9d42210c_2129x932.heic 1272w, https://substackcdn.com/image/fetch/$s_!xkoj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F392819f1-65f2-4637-9bbb-fb8b9d42210c_2129x932.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xkoj!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F392819f1-65f2-4637-9bbb-fb8b9d42210c_2129x932.heic" width="1200" height="525" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/392819f1-65f2-4637-9bbb-fb8b9d42210c_2129x932.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:637,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:86336,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176729823?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F392819f1-65f2-4637-9bbb-fb8b9d42210c_2129x932.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!xkoj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F392819f1-65f2-4637-9bbb-fb8b9d42210c_2129x932.heic 424w, https://substackcdn.com/image/fetch/$s_!xkoj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F392819f1-65f2-4637-9bbb-fb8b9d42210c_2129x932.heic 848w, https://substackcdn.com/image/fetch/$s_!xkoj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F392819f1-65f2-4637-9bbb-fb8b9d42210c_2129x932.heic 1272w, https://substackcdn.com/image/fetch/$s_!xkoj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F392819f1-65f2-4637-9bbb-fb8b9d42210c_2129x932.heic 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 role="img" 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><title></title><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>What do we achieve with replication? Primarily:</p><ul><li><p><strong>High availability and fault tolerance:</strong> If one database node crashes or becomes unreachable, the system can automatically fail over to a replica which has the same data. The app continues with minimal interruption. By keeping copies in multiple geographic locations, you can survive regional outages as well - one data center&#8217;s issue won&#8217;t take down the entire service. For example, many cloud databases keep a primary in one zone and a replica in another, so that even a data center outage doesn&#8217;t cause data loss or downtime.</p></li><li><p><strong>Read scaling and performance:</strong> By having multiple copies of the data, you can spread read queries among them. As mentioned, a primary-replica setup lets you add read capacity easily - 10 replicas can handle 10&#215; the read traffic of a single server (roughly). Also, if you have users around the world, you might place replicas in different regions. Then a user in Europe can read from a database copy located in Europe, reducing latency, while users in America hit the US replica. Each sees faster response times because the data is geographically closer. </p></li></ul><blockquote><p><strong>Note:</strong> Writes are not scaled in the primary-replica model (all go to the primary), but some distributed databases offer multi-leader or sharded-writes to spread write load too.</p></blockquote><ul><li><p><strong>Disaster recovery and backups:</strong> Replication can be used to maintain a live backup of your database. For instance, you might have your primary in one cloud provider and a replica in another provider or region. If a catastrophe hits one, the other still has your data. Replicas can also be used to run backups or heavy analytical queries without impacting the primary&#8217;s performance. Essentially, replication provides peace of mind that one failure won&#8217;t destroy your only copy of data.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!jCI5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F962be111-bde6-4c94-a467-62e80b0e451e_1629x1169.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jCI5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F962be111-bde6-4c94-a467-62e80b0e451e_1629x1169.heic 424w, https://substackcdn.com/image/fetch/$s_!jCI5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F962be111-bde6-4c94-a467-62e80b0e451e_1629x1169.heic 848w, https://substackcdn.com/image/fetch/$s_!jCI5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F962be111-bde6-4c94-a467-62e80b0e451e_1629x1169.heic 1272w, https://substackcdn.com/image/fetch/$s_!jCI5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F962be111-bde6-4c94-a467-62e80b0e451e_1629x1169.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jCI5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F962be111-bde6-4c94-a467-62e80b0e451e_1629x1169.heic" width="1456" height="1045" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/962be111-bde6-4c94-a467-62e80b0e451e_1629x1169.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1045,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:90742,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176729823?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F962be111-bde6-4c94-a467-62e80b0e451e_1629x1169.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!jCI5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F962be111-bde6-4c94-a467-62e80b0e451e_1629x1169.heic 424w, https://substackcdn.com/image/fetch/$s_!jCI5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F962be111-bde6-4c94-a467-62e80b0e451e_1629x1169.heic 848w, https://substackcdn.com/image/fetch/$s_!jCI5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F962be111-bde6-4c94-a467-62e80b0e451e_1629x1169.heic 1272w, https://substackcdn.com/image/fetch/$s_!jCI5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F962be111-bde6-4c94-a467-62e80b0e451e_1629x1169.heic 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 role="img" 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><title></title><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>If partitioning was like organizing your closet, and sharding like opening new library branches, <strong>replication is like making photocopies of important documents and storing them in multiple safes</strong>. If one safe (or one house) burns down, your documents aren&#8217;t lost - a copy exists somewhere else. It&#8217;s all about protecting data by redundancy. You pay a cost in complexity (keeping copies in sync) and sometimes in write latency (especially if using synchronous replication), but you gain a lot in terms of safety.</p><p>One important aspect to note is <strong>consistency</strong>: depending on how replication is configured, there may be a lag between a write on the primary and that write appearing on a replica. In asynchronous replication, the primary doesn&#8217;t wait for replicas to catch up - it sends the update and moves on - so a replica might be a few seconds (or more) behind. This is known as <em>replication lag</em>, and it means if you read from a replica right after writing to the primary, you might not see the latest data.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a> Many systems solve this by directing freshly updated users to the primary (read-your-writes consistency), or by using <strong>synchronous replication</strong> (the primary waits for replicas to confirm writes, which ensures strong consistency at the cost of higher latency). As an application designer, you get to choose the trade-off: immediate consistency vs. higher performance. In any case, replication gives you the ability to <strong>recover</strong> or <strong>scale reads</strong> in ways a single database cannot.</p><h1>&#129504; How these concepts work together</h1><pre><code><code>Partitioned tables &#8594; Sharded across regions &#8594; Replicated for redundancy</code></code></pre><p>In real-world architectures, partitioning, sharding, and replication are not mutually exclusive - they&#8217;re <strong>often used together</strong> in layers to handle different aspects of scale. For example, you might first partition a very large table into subtables by category or date, and then <strong>shard</strong> those partitions across multiple servers (perhaps by region or hash of a key), and finally <strong>replicate</strong> each shard to have a standby copy. A concrete scenario could look like this:</p><ul><li><p>You partition your database by function - user data vs. product data vs. logs (organizing by domain).</p></li><li><p>Within the user data, you shard by region, so EU users are handled by a different server cluster than US users, for performance and regulatory reasons.</p></li><li><p>Each of those regional shards is replicated to multiple nodes, so it remains available if one node fails.</p></li></ul><p>These strategies can be combined in many ways. In fact, architects <strong>recommend considering all three</strong> when designing a scalable data infrastructure. It&#8217;s common, for instance, to <strong>shard data then vertically partition within each shard</strong> for manageability. And almost any sharded system will employ replication as well, because more machines mean more points of failure that you have to plan for.</p><p>Think of partitioning, sharding, and replication as complementary tools:</p><ul><li><p>Partitioning makes individual <strong>databases</strong> more efficient by keeping each piece lean and focused.</p></li><li><p>Sharding allows you to <strong>add more machines</strong> to handle load by spreading the data horizontally.</p></li><li><p>Replication makes the system <strong>resilient</strong> by providing backups and distributed access.</p></li></ul><p>Together, these techniques let modern databases scale <strong>without a single node carrying all the burden</strong>. A system like Apache Cassandra, for example, automatically partitions data across many nodes and also replicates each piece of data to multiple nodes<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-6" href="#footnote-6" target="_self">6</a> - it&#8217;s sharding and replication combined, yielding a distributed store with no single point of failure. Similarly, cloud databases like Google Cloud Spanner or Amazon DynamoDB partition data and keep replicas across availability zones. Even a traditional SQL database like PostgreSQL can be manually sharded and set up with replication.</p><p>The key takeaway is that <strong>real scalability is achieved by blending these approaches</strong>. Each one addresses different challenges of growth (performance, capacity, availability), and together they ensure that as your application scales to millions of users, it remains fast and fault-tolerant. Modern architectures embrace this: your data gets <em>organized, distributed, and duplicated</em> in clever ways so that no one machine is a bottleneck or a single point of failure. It&#8217;s truly a dance of <strong>speed, scale, and safety</strong> working in harmony.</p><div><hr></div><p><strong>&#128236; If this helped you see the big picture&#8230;</strong>  </p><p>I write about software architecture, systems that scale, and how to reason about complexity without panic.  </p><p><strong>Subscribe if you want more posts like this - explained calmly and from first principles.</strong></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h1>&#9878;&#65039; The hidden costs &#8212; when splitting gets hard</h1><p>Before you enthusiastically break your database into 100 pieces, it&#8217;s important to acknowledge the trade-offs. <strong>Splitting a database (through any combination of partitioning, sharding, and replication) introduces complexity</strong>. Here are some of the hidden costs and challenges to be aware of:</p><ul><li><p><strong>Complex queries become tricky:</strong> When data is all in one place, you can join tables and run analytical queries easily. In a sharded or heavily partitioned system, a query that needs data from multiple shards/partitions is much harder. For example, joining a user profile (in shard A) with that user&#8217;s order history (in shard B) might require your application to query both shards and merge the results manually. Cross-shard joins or aggregations are either slow, require additional tooling, or are sometimes impossible. Simply put, distributing data <strong>adds complexity to querying</strong> - developers need to write more logic, or use middleware, to gather data from multiple sources. This is a big reason why sharding is often delayed until absolutely necessary.</p></li><li><p><strong>Operational overhead:</strong> Running one database is hard enough; running say 10 shards * 3 replicas each = 30 databases can be a headache. More servers mean more things that can go wrong. Routine tasks like backups, restores, schema migrations, or software upgrades have to be performed on each partition/shard, often in a coordinated way. If you change a table schema, you now have to update it across all shards consistently. If you want to back up data, you might have to script backups for dozens of servers. There&#8217;s also a maintenance cost in monitoring - keeping an eye on load and health across all the pieces. This increased administrative burden can lead to errors if not managed carefully. In short, a distributed system is <em>harder to manage</em> than a single-node system.</p></li><li><p><strong>Consistency trade-offs:</strong> As discussed, replication (especially asynchronous) can lead to <strong>eventual consistency</strong> issues - where reads might temporarily see old data until the replicas catch up. Likewise, in multi-master setups, you might get conflicting updates that need resolution. Even in sharded systems, maintaining global constraints or consistency can be challenging. For instance, ensuring a unique username across all shards means each new username might need to be checked against all shards - which is slow - or you accept that duplicates might happen in different shards. Distributed systems often have to choose between strong consistency and high availability (per the <strong>CAP theorem</strong>). So, splitting data may force you to deal with moments of inconsistency or more complex consistency mechanisms.</p></li><li><p><strong>Balancing and hot spots:</strong> Deciding how to split data is tricky; if you get it wrong, you might end up with an uneven distribution. One shard could become a <strong>hot spot</strong> - handling a disproportionate amount of traffic or storing much more data than others. For example, if an online game shards players by the first letter of their username, and it turns out most players choose names starting with &#8220;<em>S</em>&#8221;, then the &#8220;<em>S</em>&#8221; shard will lag under load. We mentioned range sharding has this risk. Mitigating it might involve re-sharding (splitting a shard into two, or moving some data to another shard) which is a non-trivial operation that can require downtime or careful data migration. Similarly, with partitioning, if one partition grows much faster, you might need to redefine the partition boundaries. <strong>Maintaining an even balance</strong> as data and access patterns change is an ongoing challenge. It often requires monitoring and possibly auto-scaling or re-partitioning mechanisms to avoid hot spots.</p></li></ul><p>It&#8217;s easy to split the wardrobe; it can be harder to find your favorite shirt afterwards. In other words, distributing data solves a lot of scaling issues, but it also means <strong>you&#8217;ve shifted complexity from hardware to software</strong>. You&#8217;ll need smart logic to query, integrity checks across shards, robust monitoring, and an ops team ready to handle failures in a distributed environment. These are by no means deal-breakers - every large-scale system deals with them - but they are the &#8220;<em>cost of doing business</em>&#8221; for scaling out.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!XXrI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa71b58b4-3674-426a-a075-2dd0b4a8733e_2845x1669.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!XXrI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa71b58b4-3674-426a-a075-2dd0b4a8733e_2845x1669.heic 424w, https://substackcdn.com/image/fetch/$s_!XXrI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa71b58b4-3674-426a-a075-2dd0b4a8733e_2845x1669.heic 848w, https://substackcdn.com/image/fetch/$s_!XXrI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa71b58b4-3674-426a-a075-2dd0b4a8733e_2845x1669.heic 1272w, https://substackcdn.com/image/fetch/$s_!XXrI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa71b58b4-3674-426a-a075-2dd0b4a8733e_2845x1669.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!XXrI!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa71b58b4-3674-426a-a075-2dd0b4a8733e_2845x1669.heic" width="1200" height="703.8461538461538" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a71b58b4-3674-426a-a075-2dd0b4a8733e_2845x1669.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:854,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:161503,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176729823?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa71b58b4-3674-426a-a075-2dd0b4a8733e_2845x1669.heic&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!XXrI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa71b58b4-3674-426a-a075-2dd0b4a8733e_2845x1669.heic 424w, https://substackcdn.com/image/fetch/$s_!XXrI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa71b58b4-3674-426a-a075-2dd0b4a8733e_2845x1669.heic 848w, https://substackcdn.com/image/fetch/$s_!XXrI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa71b58b4-3674-426a-a075-2dd0b4a8733e_2845x1669.heic 1272w, https://substackcdn.com/image/fetch/$s_!XXrI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa71b58b4-3674-426a-a075-2dd0b4a8733e_2845x1669.heic 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 role="img" 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><title></title><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><h1>&#128172; The philosophy of scale</h1><blockquote><p>Splitting a database isn&#8217;t a failure - it&#8217;s evolution.</p><p>Growth always brings complexity, and architecture is about choosing where to place it.</p><p>The best systems don&#8217;t avoid scale - they embrace it by dividing their load wisely, ensuring no single node carries the world alone.</p></blockquote><p>In the end, moving to partitioning, sharding, or replication is a sign of success: it means your application grew to the point that a simple approach no longer sufficed. Rather than fearing this complexity, we manage it. Good engineering is not about preventing complexity (which is impossible at large scale), but about <strong>organizing complexity</strong> in a way that is maintainable and robust. By splitting a big problem (one giant overloaded database) into smaller ones (several well-organized, cooperative data stores), we make the system as a whole more scalable and reliable. No single database carries the entire burden, and that&#8217;s a very good thing for longevity.</p><div><hr></div><p><strong>&#128172; Every system reaches this point eventually.</strong></p><p>Where have you seen things break first - data size, traffic, or reliability?</p><p>Share your experience in the comments.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/why-databases-get-split-sharding/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/why-databases-get-split-sharding/comments"><span>Leave a comment</span></a></p><div><hr></div><h1>&#9997;&#65039; Recap</h1><p>One database can&#8217;t scale forever - at a certain point, splitting your data becomes inevitable for growth.</p><ul><li><p><strong>Partitioning</strong> = organizing a single dataset into smaller segments (by table, column, or row subsets) for clarity and performance benefits (faster queries on smaller chunks, easier maintenance).</p></li><li><p><strong>Sharding</strong> = distributing data across multiple <em>servers/databases</em> for horizontal scalability. Each shard holds a portion of the data, allowing the overall system to handle more load by adding machines.</p></li><li><p><strong>Replication</strong> = duplicating data onto multiple nodes for safety and high availability. If one node fails, a replica can serve the data; plus, read traffic can be spread out to improve throughput.</p></li></ul><p>Real-world systems often <strong>combine all three</strong> - partitioning for manageability, sharding for scale, and replication for resilience &#8211; achieving a balance of performance and redundancy. Embracing these patterns is how we evolve a simple system into one that can handle internet-scale demands without fear.</p><div><hr></div><p><strong>&#129309; Architecture gets easier when we learn it together.</strong></p><p>Refer this article to a teammate, or friend who&#8217;s learning backend  or system design fundamentals.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/leaderboard?&amp;utm_source=post&quot;,&quot;text&quot;:&quot;Refer a friend&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/leaderboard?&amp;utm_source=post"><span>Refer a friend</span></a></p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p><a href="https://learn.microsoft.com/en-us/azure/architecture/best-practices/data-partitioning">Data partitioning guidance</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p><a href="https://planetscale.com/blog/sharding-vs-partitioning-whats-the-difference">Sharding vs. partitioning: What&#8217;s the difference?</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p><a href="https://aerospike.com/blog/what-is-database-replication">What is database replication, and why is it important?</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-4" href="#footnote-anchor-4" class="footnote-number" contenteditable="false" target="_self">4</a><div class="footnote-content"><p><a href="https://bugfree.ai/knowledge-hub/master-slave-vs-multi-master-replication">Master-Slave vs Multi-Master Replication</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-5" href="#footnote-anchor-5" class="footnote-number" contenteditable="false" target="_self">5</a><div class="footnote-content"><p><a href="https://medium.com/@nyshnt/understanding-database-replication-ensuring-consistency-and-performance-in-large-scale-3c2bdf1d25a4">Understanding Database Replication: Ensuring Consistency and Performance in Large-Scale Applications</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-6" href="#footnote-anchor-6" class="footnote-number" contenteditable="false" target="_self">6</a><div class="footnote-content"><p><a href="https://docs.datastax.com/en/cassandra-oss/3.x/cassandra/architecture/archDataDistributeAbout.html">Data distribution and replication</a></p></div></div>]]></content:encoded></item><item><title><![CDATA[What it means for a system to be consistent — and why it does not always have to be]]></title><description><![CDATA[System design fundamentals]]></description><link>https://iam.slys.dev/p/what-it-means-for-a-system-to-be</link><guid isPermaLink="false">https://iam.slys.dev/p/what-it-means-for-a-system-to-be</guid><dc:creator><![CDATA[Jakub Slys 🤖]]></dc:creator><pubDate>Mon, 01 Dec 2025 21:22:31 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!ge6h!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65940e46-184f-412d-b4d3-3ae58ab101d8_1536x1024.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_!ge6h!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65940e46-184f-412d-b4d3-3ae58ab101d8_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ge6h!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65940e46-184f-412d-b4d3-3ae58ab101d8_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!ge6h!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65940e46-184f-412d-b4d3-3ae58ab101d8_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!ge6h!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65940e46-184f-412d-b4d3-3ae58ab101d8_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!ge6h!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65940e46-184f-412d-b4d3-3ae58ab101d8_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ge6h!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65940e46-184f-412d-b4d3-3ae58ab101d8_1536x1024.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/65940e46-184f-412d-b4d3-3ae58ab101d8_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2644937,&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://iam.slys.dev/i/176729656?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65940e46-184f-412d-b4d3-3ae58ab101d8_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ge6h!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65940e46-184f-412d-b4d3-3ae58ab101d8_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!ge6h!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65940e46-184f-412d-b4d3-3ae58ab101d8_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!ge6h!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65940e46-184f-412d-b4d3-3ae58ab101d8_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!ge6h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65940e46-184f-412d-b4d3-3ae58ab101d8_1536x1024.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 role="img" 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><title></title><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><blockquote><p>Have you ever sent a bank transfer and noticed it didn&#8217;t appear right away?<br>Or added something to your online cart, only to see it disappear after refreshing the page?</p><p>Nothing&#8217;s broken.<br>That&#8217;s just how distributed systems work - in a world where <strong>truth travels in pieces.</strong></p></blockquote><p>In moments like these, it may feel like the digital world is <em>out of sync</em>. But in reality, nothing is malfunctioning at all &#8211; it&#8217;s simply the nature of distributed systems. Data and truth don&#8217;t arrive everywhere <strong>instantly</strong>; they travel in pieces, catching up from one server to another. This means different parts of a system might briefly disagree on what &#8220;<em>truth</em>&#8221; is.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-88p!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F182e5eeb-b449-4b20-a393-99425a3a2b37_1741x877.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-88p!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F182e5eeb-b449-4b20-a393-99425a3a2b37_1741x877.png 424w, https://substackcdn.com/image/fetch/$s_!-88p!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F182e5eeb-b449-4b20-a393-99425a3a2b37_1741x877.png 848w, https://substackcdn.com/image/fetch/$s_!-88p!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F182e5eeb-b449-4b20-a393-99425a3a2b37_1741x877.png 1272w, https://substackcdn.com/image/fetch/$s_!-88p!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F182e5eeb-b449-4b20-a393-99425a3a2b37_1741x877.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-88p!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F182e5eeb-b449-4b20-a393-99425a3a2b37_1741x877.png" width="1456" height="733" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/182e5eeb-b449-4b20-a393-99425a3a2b37_1741x877.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:733,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:134222,&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;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176729656?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F182e5eeb-b449-4b20-a393-99425a3a2b37_1741x877.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_!-88p!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F182e5eeb-b449-4b20-a393-99425a3a2b37_1741x877.png 424w, https://substackcdn.com/image/fetch/$s_!-88p!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F182e5eeb-b449-4b20-a393-99425a3a2b37_1741x877.png 848w, https://substackcdn.com/image/fetch/$s_!-88p!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F182e5eeb-b449-4b20-a393-99425a3a2b37_1741x877.png 1272w, https://substackcdn.com/image/fetch/$s_!-88p!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F182e5eeb-b449-4b20-a393-99425a3a2b37_1741x877.png 1456w" sizes="100vw"></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 role="img" 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><title></title><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>Instead of being a binary attribute (consistent vs. inconsistent), <strong>consistency</strong> in distributed computing is more of a sliding scale &#8211; a balance between accuracy, speed, and the realities of networked life. Understanding this balance is key to designing systems that are both reliable and responsive.</p><div><hr></div><p>&#128161; <strong>Like this kind of thinking?</strong></p><p>I write weekly about distributed systems, architecture, and developer-friendly design - all in plain English. </p><p>&#128236; <strong>Subscribe here</strong> to get the next one straight to your inbox.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h1>&#129513; What &#8220;consistency&#8221; really means</h1><p>When engineers talk about a system being &#8220;<em>consistent</em>&#8221;, they mean that everyone (or every part of the system) sees the <strong>same data at the same time</strong>. In an ideal world, the moment something changes &#8211; like you adding an item to your cart or transferring money &#8211; <strong>all</strong> parts of the system would immediately reflect that change. Your friends in a group chat would all see the latest message simultaneously, no matter where they are.</p><p>In practice, especially in distributed systems spread across multiple servers or regions, this ideal is hard to achieve. Data often needs time to &#8220;<em>catch up</em>&#8221; between nodes. One server might record an update a few seconds (or milliseconds) before another. Imagine a group of friends trying to plan dinner over text messages. Some reply instantly, others take an hour. Only after some time does everyone finally agree on the same plan. That&#8217;s a pretty good metaphor for <strong>eventual consistency</strong> &#8211; the idea that a system&#8217;s parts will <strong>eventually</strong> agree on the truth, even if they&#8217;re temporarily out of sync.</p><p>Crucially, consistency isn&#8217;t all-or-nothing. It&#8217;s tempting to think a system is either perfectly consistent or completely broken, but there&#8217;s a lot of gray area in between. We often <strong>trade off</strong> a bit of immediate consistency to gain other benefits (like performance or uptime). The next sections will explore why those trade-offs exist and how modern systems manage them.</p><h1>&#9881;&#65039; The CAP theorem &#8212; three letters that changed everything</h1><p>In the early 2000s, computer scientist <em>Eric Brewer</em> proposed something known as the <strong>CAP theorem<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></strong>. This theorem frames a fundamental tension in distributed systems using three properties:</p><ul><li><p><strong>C - Consistency:</strong> All nodes see the same data at the same time. After you write data, any read from any node returns that new data.</p></li><li><p><strong>A &#8211; Availability:</strong> The system always responds to requests. Every request gets a response (even if some nodes are down), although the response might not always contain the very latest data.</p></li><li><p><strong>P &#8211; Partition Tolerance:</strong> The system keeps working despite network failures or &#8220;<em>partitions</em>&#8221; that temporarily break the network into isolated pieces.</p></li></ul><p>Brewer&#8217;s insight (later formalized by <em>Gilbert</em> and <em>Lynch</em>) was that in a distributed system <strong>you cannot have all three of these at once</strong>. The CAP theorem famously says: <em>pick two, and sacrifice the third</em>. If you want consistency and availability at all times, your system cannot tolerate certain network failures. If you need to survive network partitions (and most distributed systems do), you face a choice: <strong>favor consistency or favor availability</strong>. In theory, we&#8217;d love systems that are fast, always up, and perfectly accurate; in reality, we&#8217;re forced to compromise.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qmtc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc49ffe6f-3d30-4999-beb7-d2e0c3a13bf4_1848x1514.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qmtc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc49ffe6f-3d30-4999-beb7-d2e0c3a13bf4_1848x1514.png 424w, https://substackcdn.com/image/fetch/$s_!qmtc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc49ffe6f-3d30-4999-beb7-d2e0c3a13bf4_1848x1514.png 848w, https://substackcdn.com/image/fetch/$s_!qmtc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc49ffe6f-3d30-4999-beb7-d2e0c3a13bf4_1848x1514.png 1272w, https://substackcdn.com/image/fetch/$s_!qmtc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc49ffe6f-3d30-4999-beb7-d2e0c3a13bf4_1848x1514.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qmtc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc49ffe6f-3d30-4999-beb7-d2e0c3a13bf4_1848x1514.png" width="1456" height="1193" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c49ffe6f-3d30-4999-beb7-d2e0c3a13bf4_1848x1514.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1193,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:205244,&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://iam.slys.dev/i/176729656?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc49ffe6f-3d30-4999-beb7-d2e0c3a13bf4_1848x1514.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_!qmtc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc49ffe6f-3d30-4999-beb7-d2e0c3a13bf4_1848x1514.png 424w, https://substackcdn.com/image/fetch/$s_!qmtc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc49ffe6f-3d30-4999-beb7-d2e0c3a13bf4_1848x1514.png 848w, https://substackcdn.com/image/fetch/$s_!qmtc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc49ffe6f-3d30-4999-beb7-d2e0c3a13bf4_1848x1514.png 1272w, https://substackcdn.com/image/fetch/$s_!qmtc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc49ffe6f-3d30-4999-beb7-d2e0c3a13bf4_1848x1514.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 role="img" 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><title></title><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>This doesn&#8217;t mean a system can never be consistent, available, and partition-tolerant in different moments. Rather, CAP highlights a design <strong>priority</strong>: when a network partition happens, would you rather your system go offline (to remain consistent) or stay online but potentially show slightly inconsistent data? Different systems answer this question differently, which leads us to CP vs. AP systems.</p><h1>&#129504; How systems choose between consistency and availability</h1><p>Real-world systems have to make a conscious choice when designing for the CAP trade-off: <strong>consistency or availability</strong> (since we assume partitions will happen eventually). Depending on the domain, one is often valued over the other.</p><p><strong>CP systems (Consistency + Partition tolerance):</strong> These systems choose to remain consistent even if it means not always being fully available during a network problem. A classic example is a banking system. If there&#8217;s any uncertainty or network hiccup, a bank&#8217;s software would rather refuse your transaction or make you wait than show the wrong balance. Accuracy is paramount - no one wants to see money &#8220;<em>appear</em>&#8221; or &#8220;<em>disappear</em>&#8221; incorrectly. In fact, when designing a financial system, consistency is considered crucial, even if that means occasionally sacrificing availability. In a CP system, if a few servers can&#8217;t talk to each other (a partition), they might halt some operations or switch to a read-only mode until they can synchronize, ensuring no conflicting data gets created. It&#8217;s a cautious approach: &#8220;<em>Let&#8217;s pause until we&#8217;re sure everyone&#8217;s on the same page</em>&#8221;.</p><p><strong>AP systems (Availability + Partition tolerance):</strong> These systems take the opposite approach: they prioritize uptime and responsiveness, even if it means some parts of the system might be briefly out-of-date. Many social networks and online services fall into this category. You&#8217;ve probably noticed that your social media feed will load with older posts rather than showing an error &#8211; that&#8217;s on purpose. You&#8217;d prefer to see <strong>something</strong> rather than nothing. Facebook, Twitter, Instagram &#8211; all these platforms tolerate showing you data that might not be perfectly up-to-the-second, as long as the service stays up and interactive. They embrace <strong>eventual consistency</strong> under the hood. A new post might appear immediately to the author, while followers see it moments later; such temporary inconsistency is acceptable for the sake of availability and user experience<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a>. In an AP system, even if parts of the network are cut off from each other, each partition can continue accepting requests (reads and writes) and sync up later. It&#8217;s a &#8220;<em>show something now, fix it later</em>&#8221; philosophy.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!AT65!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b2ce146-7df1-4655-ac6b-44425e5274cb_2910x1344.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!AT65!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b2ce146-7df1-4655-ac6b-44425e5274cb_2910x1344.png 424w, https://substackcdn.com/image/fetch/$s_!AT65!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b2ce146-7df1-4655-ac6b-44425e5274cb_2910x1344.png 848w, https://substackcdn.com/image/fetch/$s_!AT65!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b2ce146-7df1-4655-ac6b-44425e5274cb_2910x1344.png 1272w, https://substackcdn.com/image/fetch/$s_!AT65!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b2ce146-7df1-4655-ac6b-44425e5274cb_2910x1344.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!AT65!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b2ce146-7df1-4655-ac6b-44425e5274cb_2910x1344.png" width="1200" height="553.8461538461538" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3b2ce146-7df1-4655-ac6b-44425e5274cb_2910x1344.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:672,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:171333,&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://iam.slys.dev/i/176729656?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b2ce146-7df1-4655-ac6b-44425e5274cb_2910x1344.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!AT65!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b2ce146-7df1-4655-ac6b-44425e5274cb_2910x1344.png 424w, https://substackcdn.com/image/fetch/$s_!AT65!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b2ce146-7df1-4655-ac6b-44425e5274cb_2910x1344.png 848w, https://substackcdn.com/image/fetch/$s_!AT65!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b2ce146-7df1-4655-ac6b-44425e5274cb_2910x1344.png 1272w, https://substackcdn.com/image/fetch/$s_!AT65!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b2ce146-7df1-4655-ac6b-44425e5274cb_2910x1344.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 role="img" 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><title></title><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>The choice between CP and AP often boils down to the question: <strong>What matters more for this application, absolute accuracy or uptime?</strong> In a bank, you&#8217;d rather wait a bit longer and <em>see the correct balance</em> (consistency over availability). On Instagram or Twitter, you&#8217;d rather see <strong>something</strong> now &#8211; maybe a slightly stale feed &#8211; than encounter a &#8220;<em>service unavailable</em>&#8221; error (availability over immediate consistency). Neither approach is &#8220;<em>wrong</em>&#8221; - they&#8217;re just optimized for different goals.</p><h1>&#129518; Types of consistency (with human analogies)</h1><p>Consistency isn&#8217;t a single setting but a spectrum of models, each with its own guarantees about how and when data updates become visible. To demystify some common consistency levels, let&#8217;s look at a few in simple terms, along with analogies from everyday life:</p><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/Czdk1/3/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4f4c8644-de91-4039-a48b-1eb6289529f8_1220x952.png&quot;,&quot;thumbnail_url_full&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1a732276-27f5-404a-bede-5c660b5fe55b_1220x1022.png&quot;,&quot;height&quot;:373,&quot;title&quot;:&quot;Consistency levels&quot;,&quot;description&quot;:&quot;&quot;}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/Czdk1/3/" width="730" height="373" frameborder="0" scrolling="no"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><p>Each of these offers a different balance between immediacy and simplicity. <strong>Strong consistency</strong> is the intuitive ideal &#8211; as soon as something changes, every user and every node in the system sees the same latest data. It&#8217;s like having a single up-to-date copy of the truth that everyone consults. This is great for correctness, but it can be slow or impractical in a distributed setting (imagine if our group chat required every message to be confirmed by every phone in the chat before anyone sees it &#8211; that would be painfully slow!).</p><p>At the other end, <strong>eventual consistency</strong> is very flexible. It doesn&#8217;t promise that everyone sees the latest data <strong>right now</strong> &#8211; only that if you stop making updates and wait awhile, all replicas will <strong>eventually</strong> catch up to the same state. Different users might see slightly different information for a short time, but the differences disappear over time. Many large-scale systems use this model to stay fast and available. It&#8217;s like those text messages: you might get replies with delay, but eventually everyone gets all the messages and the conversation makes sense as a whole.</p><p><strong>Causal consistency</strong> is a bit smarter about ordering &#8211; it ensures that causally related updates (like a post and then a comment on that post) are seen in the correct order everywhere<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a>. If event A causes event B, no one will see B without seeing A first. For example, your reply will never appear to have happened before the comment that triggered it. This model relaxes the requirement of strong consistency (which enforces one single timeline for all events) and allows unrelated events to be observed in different orders by different nodes, as long as the cause-and-effect relationships are preserved. It&#8217;s a nice middle ground that many systems strive for &#8211; improving performance (by not globally ordering everything) without confusing users about what caused what.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!eqw_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefc702ff-4054-47c8-a273-580f81946394_2039x1625.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eqw_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefc702ff-4054-47c8-a273-580f81946394_2039x1625.png 424w, https://substackcdn.com/image/fetch/$s_!eqw_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefc702ff-4054-47c8-a273-580f81946394_2039x1625.png 848w, https://substackcdn.com/image/fetch/$s_!eqw_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefc702ff-4054-47c8-a273-580f81946394_2039x1625.png 1272w, https://substackcdn.com/image/fetch/$s_!eqw_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefc702ff-4054-47c8-a273-580f81946394_2039x1625.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!eqw_!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefc702ff-4054-47c8-a273-580f81946394_2039x1625.png" width="1200" height="956.0439560439561" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/efc702ff-4054-47c8-a273-580f81946394_2039x1625.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1160,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:277629,&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://iam.slys.dev/i/176729656?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefc702ff-4054-47c8-a273-580f81946394_2039x1625.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!eqw_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefc702ff-4054-47c8-a273-580f81946394_2039x1625.png 424w, https://substackcdn.com/image/fetch/$s_!eqw_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefc702ff-4054-47c8-a273-580f81946394_2039x1625.png 848w, https://substackcdn.com/image/fetch/$s_!eqw_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefc702ff-4054-47c8-a273-580f81946394_2039x1625.png 1272w, https://substackcdn.com/image/fetch/$s_!eqw_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefc702ff-4054-47c8-a273-580f81946394_2039x1625.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 role="img" 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><title></title><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>Finally, <strong>read-your-writes</strong> consistency is a guarantee often applied on a per-user basis. It doesn&#8217;t concern multiple users agreeing; it just ensures <strong>you</strong> don&#8217;t get confused by your own actions. After you make an update, when you go to read that same data, you&#8217;ll at least see your own update reflected<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a>. For instance, if you edit your profile and then refresh the page, the new info should be there for you. Even if some distant server hasn&#8217;t gotten the update yet, the system will make sure your reads fetch a copy that includes your changes. This avoids the &#8220;<em>Didn&#8217;t I just change that?</em>&#8221; frustration. It&#8217;s a pragmatic way to make an eventually consistent system feel more solid to a user by giving them a consistent view of <strong>their</strong> own actions.</p><blockquote><p><strong>Insight:</strong> Think of these consistency models as different rhythms at which a distributed system <strong>reaches the truth</strong>. Strong consistency is like a synchronized orchestra &#8211; strict but slow. Eventual consistency is more like a jam session where everyone will harmonize, but not instantly. The other models (causal, read-your-writes, etc.) add rules to make the tune sound &#8220;<em>right</em>&#8221; to the listeners. Modern system design often blends these models, choosing stricter consistency for some operations and looser consistency for others. In fact, many systems treat consistency as a spectrum and <strong>mix models</strong> as needed &#8211; for example, ensuring read-your-writes and causal ordering to keep users happy, while still allowing some eventual behavior for scalability.</p></blockquote><h1>&#128260; How consistency affects the user</h1><p>From a user&#8217;s perspective, consistency is never about the theory &#8211; it&#8217;s about how the app feels. Interestingly, users often don&#8217;t notice (or care about) whether a system is strongly or eventually consistent, as long as the <strong>experience</strong> makes sense. The onus is on us as engineers to hide inconsistencies and make things feel natural.</p><p>Great systems cleverly mask the quirks of distributed data. A common technique is using <strong>optimistic updates</strong> on the front-end: when you perform an action (like sending a message or &#8220;<em>liking</em>&#8221; a post), the app immediately reflects that change in the UI without waiting for the server to confirm. For example, your email application might show a new email in your &#8220;<em>Sent</em>&#8221; folder instantly, while in reality the server is still in the process of delivering it. This gives you instant feedback. Under the hood, the system will reconcile any discrepancy afterward (if the send fails or the server disagrees, you might see a small &#8220;<em>retry</em>&#8221; or &#8220;<em>syncing&#8230;</em>&#8221; notice). By showing local results first and syncing in the background, the system feels <strong>responsive</strong> and &#8220;<em>consistent enough</em>&#8221; from the user&#8217;s point of view.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!MBYv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42c8a8f8-b242-4176-9bfe-e31388d36f5c_1024x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MBYv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42c8a8f8-b242-4176-9bfe-e31388d36f5c_1024x1024.png 424w, https://substackcdn.com/image/fetch/$s_!MBYv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42c8a8f8-b242-4176-9bfe-e31388d36f5c_1024x1024.png 848w, https://substackcdn.com/image/fetch/$s_!MBYv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42c8a8f8-b242-4176-9bfe-e31388d36f5c_1024x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!MBYv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42c8a8f8-b242-4176-9bfe-e31388d36f5c_1024x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!MBYv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42c8a8f8-b242-4176-9bfe-e31388d36f5c_1024x1024.png" width="1024" height="1024" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/42c8a8f8-b242-4176-9bfe-e31388d36f5c_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;:1384245,&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://iam.slys.dev/i/176729656?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42c8a8f8-b242-4176-9bfe-e31388d36f5c_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_!MBYv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42c8a8f8-b242-4176-9bfe-e31388d36f5c_1024x1024.png 424w, https://substackcdn.com/image/fetch/$s_!MBYv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42c8a8f8-b242-4176-9bfe-e31388d36f5c_1024x1024.png 848w, https://substackcdn.com/image/fetch/$s_!MBYv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42c8a8f8-b242-4176-9bfe-e31388d36f5c_1024x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!MBYv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42c8a8f8-b242-4176-9bfe-e31388d36f5c_1024x1024.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 role="img" 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><title></title><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><figcaption class="image-caption"><em>An email client interface showing a message moved to the Sent folder immediately after hitting &#8220;Send&#8221;, possibly with a subtle indicator that it&#8217;s still sending. The user perceives it as sent while the system finalizes delivery in the background.</em></figcaption></figure></div><p>Another strategy is to mark things as &#8220;<em>pending</em>&#8221; or &#8220;<em>updating</em>&#8221;. For instance, a mobile app might display a just-uploaded photo in your gallery right away but with a faint overlay or spinner, indicating it&#8217;s being saved to the cloud. You see it immediately, and once the server confirms the upload (or if it fails), the app updates that status (removing the spinner or showing an error). Thus, eventual consistency is happening behind the scenes, but the user experience remains smooth. </p><div><hr></div><p>&#128172; <strong>Ever noticed this in real life?</strong></p><p>Drop a comment below - I&#8217;d love to hear your thoughts on systems that felt &#8220;<em>off</em>&#8221; or surprisingly seamless. What&#8217;s one app where you&#8217;ve felt the inconsistency (or didn&#8217;t, thanks to great UX)?</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/what-it-means-for-a-system-to-be/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/what-it-means-for-a-system-to-be/comments"><span>Leave a comment</span></a></p><div><hr></div><p>In other words, the system is eventually consistent, but it <strong>feels</strong> intuitively consistent to the user. Engineering articles often note that eventual consistency is perfectly acceptable with the right UX design &#8211; e.g., showing progress indicators or using short animations to cover up the waiting.</p><p>In essence, the goal isn&#8217;t perfect data truth at every millisecond &#8211; it&#8217;s a <strong>consistent experience</strong>. Gmail, for example, will show your outgoing email as &#8220;<em>Sent</em>&#8221; immediately, giving you the confidence to move on, even though the message is actually queued and being processed behind the scenes. Social networks show your new status update to you right after you post it (thanks to read-your-writes guarantees), ensuring you&#8217;re not confused, while the system takes a bit of time to propagate that update to all your followers. Users are happy because the app behaves in a natural, snappy way &#8211; they don&#8217;t see the gears turning underneath. A well-designed distributed system often embraces eventual consistency internally but makes it <strong>feel</strong> almost like strong consistency to the end user.</p><h1>&#9878;&#65039; When consistency matters most</h1><p>Not all applications are equal when it comes to consistency needs. Some domains demand that data be absolutely up-to-date and consistent across the board, while others can tolerate a little lag or discrepancy. Knowing which is which helps engineers choose the right approach:</p><h2>&#9989; <strong>Contexts that demand strong consistency</strong></h2><ul><li><p><strong>Financial transactions (banking, payments):</strong> Money is serious business. Account balances, transfers, stock trades &#8211; these must be correct and consistent globally to prevent errors like double-spending or overdrafts. Banks will often prefer to delay or lock an operation rather than allow an inconsistent view of funds. Similarly, online trading platforms need all traders to see the same prices and account info at the same time.</p></li><li><p><strong>Medical records:</strong> In healthcare systems, showing outdated patient information could be dangerous. If one doctor&#8217;s screen shows an old medication list while another&#8217;s shows an updated list, the consequences could be life-threatening. For this reason, patient records systems lean toward strong consistency to ensure everyone sees the latest, correct data.</p></li><li><p><strong>Booking and reservation systems:</strong> If two people think they booked the last seat on a flight or the same hotel room because of a momentary inconsistency, you have a big problem. These systems often enforce strong consistency (or use transactions) to prevent double-bookings. It&#8217;s better to make one user wait or even receive an error than to allow an overlap that must be fixed later.</p></li></ul><h2>&#9989; <strong>Contexts where eventual consistency is fine (even desirable)</strong></h2><ul><li><p><strong>Social media feeds:</strong> As mentioned earlier, social platforms are a prime example. It&#8217;s not critical that every user sees every like or comment the instant it happens &#8211; a slight delay is usually unnoticeable, and the system values being always available and fast over being perfectly synchronized.</p></li><li><p><strong>Analytics dashboards:</strong> Dashboards that show website traffic, app usage, or ad metrics typically don&#8217;t need up-to-the-second accuracy. If your analytics are a minute behind real time, that&#8217;s usually acceptable. What matters is that the system can ingest data reliably and stay up, rather than being perfectly current. These systems often favor availability and partition tolerance, updating stats gradually.</p></li><li><p><strong>Caches and recommendation systems:</strong> Systems that cache data (like content delivery networks, or in-memory caches for database queries) or that serve recommendations (like &#8220;<em>people you may know</em>&#8221; or product suggestions) can tolerate some staleness. Slight delays in propagation are acceptable and help maintain global availability. For example, an e-commerce site&#8217;s &#8220;<em>popular products</em>&#8221; list might not update instantly with every single purchase; it might recompute every hour. That&#8217;s fine &#8211; users get quick responses, and the data will refresh eventually without harming the experience.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!HT_F!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F267104d3-3b76-4536-9f0e-3e9b59d925b0_1547x2623.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!HT_F!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F267104d3-3b76-4536-9f0e-3e9b59d925b0_1547x2623.png 424w, https://substackcdn.com/image/fetch/$s_!HT_F!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F267104d3-3b76-4536-9f0e-3e9b59d925b0_1547x2623.png 848w, https://substackcdn.com/image/fetch/$s_!HT_F!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F267104d3-3b76-4536-9f0e-3e9b59d925b0_1547x2623.png 1272w, https://substackcdn.com/image/fetch/$s_!HT_F!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F267104d3-3b76-4536-9f0e-3e9b59d925b0_1547x2623.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!HT_F!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F267104d3-3b76-4536-9f0e-3e9b59d925b0_1547x2623.png" width="1456" height="2469" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/267104d3-3b76-4536-9f0e-3e9b59d925b0_1547x2623.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:2469,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:284030,&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://iam.slys.dev/i/176729656?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F267104d3-3b76-4536-9f0e-3e9b59d925b0_1547x2623.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_!HT_F!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F267104d3-3b76-4536-9f0e-3e9b59d925b0_1547x2623.png 424w, https://substackcdn.com/image/fetch/$s_!HT_F!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F267104d3-3b76-4536-9f0e-3e9b59d925b0_1547x2623.png 848w, https://substackcdn.com/image/fetch/$s_!HT_F!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F267104d3-3b76-4536-9f0e-3e9b59d925b0_1547x2623.png 1272w, https://substackcdn.com/image/fetch/$s_!HT_F!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F267104d3-3b76-4536-9f0e-3e9b59d925b0_1547x2623.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 role="img" 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><title></title><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>The guiding insight here is: <strong>match the consistency model to the business needs</strong>. If a small inconsistency would cause real harm, confusion, or violate trust, that&#8217;s when you require strong consistency. If a slight delay or mismatch is essentially invisible or harmless to the user, then &#8220;<em>good enough</em>&#8221; consistency (and the performance gains that come with it) is usually exactly right. Indeed, strong consistency is crucial for things like banking, booking, and healthcare<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a>, whereas eventual consistency is often a smart choice for high-scale, user-facing systems like social networks, analytics, and caching where speed and availability are a priority.</p><h1>&#129513; Designing with imperfection in mind</h1><p>Embracing eventual or partial consistency doesn&#8217;t mean you give up on correctness &#8211; it means you design your system to <strong>handle inconsistency gracefully</strong>. In fact, building a robust distributed system is as much about planning for things to be temporarily out-of-sync as it is about trying to keep them in sync.</p><p>Here are some strategies for designing with these realities in mind:</p><ul><li><p><strong>Define where consistency matters (and where it can relax):</strong> Identify which parts of your data <strong>must</strong> be absolutely consistent and which can be more relaxed. For instance, an e-commerce site might enforce strong consistency for the inventory count of products (so you never sell more than you have in stock), but use eventual consistency for things like the product recommendation list or user reviews. By isolating the truly critical data, you can apply stricter methods there and let other areas enjoy more flexibility.</p></li><li><p><strong>Use the UI to mask delays:</strong> As discussed, a smart UI/UX can hide a lot of inconsistency. Design your user interface such that it doesn&#8217;t expose intermediate states awkwardly. If a piece of data might take time to update everywhere, show a loading state, or label it as &#8220;<em>syncing&#8230;</em>&#8221;, or update it in the background. This way, a technical delay becomes a non-issue for the user. A well-timed progress bar or a subtle &#8220;<em>refreshing</em>&#8221; indicator can turn an otherwise confusing inconsistency into an expected, even reassuring, part of the experience.</p></li><li><p><strong>Implement repair and reconciliation mechanisms:</strong> Since you expect that different parts of the system might diverge temporarily, build in processes that will <strong>reconcile</strong> data after the fact. This could be a background job that compares and merges divergent copies of data (for example, if two edits occurred separately during a partition, reconcile them once connectivity is restored), or a periodic &#8220;<em>anti-entropy</em>&#8221; task that ensures all replicas eventually converge. Even simple retry logic can help &#8211; if one service fails to get an update due to a network glitch, it can try again later. The system should have a way to <em>heal</em> its inconsistent pieces over time.</p></li><li><p><strong>Plan for idempotency and conflict resolution:</strong> In distributed systems, the same operation might happen twice or out of order due to retries and delays. Design your operations to be <strong>idempotent</strong> (so that applying the same update more than once has the same effect as doing it once) and define clear conflict resolution rules. For example, if two updates to the same record happen on different partitions, decide which one &#8220;<em>wins</em>&#8221; or how to merge them (last write wins, merge field-by-field, etc.). Having these rules in place prevents chaos when the system syncs up.</p></li><li><p><strong>Monitor and adapt:</strong> Finally, actively monitor your system&#8217;s consistency behavior. Keep an eye on metrics like replication lag (how far apart replicas are), the frequency of stale reads, or how often conflicts occur and get resolved. If you notice issues &#8211; e.g., data taking too long to become consistent, or users noticing anomalies &#8211; you can adjust your approach (maybe tighten consistency in certain areas, or improve your conflict resolution). Designing for imperfection is an ongoing process of tuning.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!wwiw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdabc3727-d164-4657-a3fd-2e01f92d577c_2658x2317.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!wwiw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdabc3727-d164-4657-a3fd-2e01f92d577c_2658x2317.png 424w, https://substackcdn.com/image/fetch/$s_!wwiw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdabc3727-d164-4657-a3fd-2e01f92d577c_2658x2317.png 848w, https://substackcdn.com/image/fetch/$s_!wwiw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdabc3727-d164-4657-a3fd-2e01f92d577c_2658x2317.png 1272w, https://substackcdn.com/image/fetch/$s_!wwiw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdabc3727-d164-4657-a3fd-2e01f92d577c_2658x2317.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!wwiw!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdabc3727-d164-4657-a3fd-2e01f92d577c_2658x2317.png" width="1200" height="1045.8791208791208" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dabc3727-d164-4657-a3fd-2e01f92d577c_2658x2317.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1269,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:262664,&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://iam.slys.dev/i/176729656?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdabc3727-d164-4657-a3fd-2e01f92d577c_2658x2317.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!wwiw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdabc3727-d164-4657-a3fd-2e01f92d577c_2658x2317.png 424w, https://substackcdn.com/image/fetch/$s_!wwiw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdabc3727-d164-4657-a3fd-2e01f92d577c_2658x2317.png 848w, https://substackcdn.com/image/fetch/$s_!wwiw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdabc3727-d164-4657-a3fd-2e01f92d577c_2658x2317.png 1272w, https://substackcdn.com/image/fetch/$s_!wwiw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdabc3727-d164-4657-a3fd-2e01f92d577c_2658x2317.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 role="img" 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><title></title><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 good distributed system isn&#8217;t one that never encounters divergent data &#8211; that&#8217;s nearly impossible at scale. Instead, it&#8217;s one that <strong>handles divergence intelligently</strong>. Think of it like a team that doesn&#8217;t panic when members initially disagree; they have processes to discuss and resolve differences and eventually reach consensus. Similarly, your system might have moments where Node A thinks X=5 while Node B thinks X=7. That&#8217;s okay if your design ensures they will reconcile (and that users aren&#8217;t adversely affected in the meantime). In other words, success is not measured by never having inconsistencies, but by how quickly and safely the system can <strong>make peace</strong> after a temporary disagreement.</p><h1>&#128172; Consistency as a philosophy</h1><p>Stepping back from the nuts and bolts, there&#8217;s a broader way to look at consistency in distributed systems. It&#8217;s less about <strong>absolute truth at every moment</strong> and more about the <strong>ability to eventually agree on truth</strong>. In life, people don&#8217;t always instantly agree or share the exact same knowledge &#8211; but with communication and time, they sync up. Distributed systems are similar: they might momentarily hold different views of the data, but as long as they have ways to share updates and resolve conflicts, they will converge on a single reality.</p><p>In fact, consistency in distributed systems is as much a <strong>philosophy of convergence</strong> as it is a technical property. We design protocols (and choose consistency models) to ensure that no matter what happens &#8211; even if updates arrive late or out of order &#8211; there are rules that will guide every part of the system toward the correct final state. The beauty is that systems, like people, <strong>don&#8217;t have to agree on everything right away</strong>. What&#8217;s crucial is that they have a path to eventually reach agreement.</p><p>This perspective can be liberating. It means that temporary inconsistency isn&#8217;t failure; it&#8217;s a normal phase of the system&#8217;s operation. By accepting that &#8220;<em>truth travels in pieces</em>&#8221; and planning accordingly, we make our systems more resilient and often more efficient. We stop chasing perfect consistency at every moment and focus on what really matters: that in the end (often a fraction of a second later, sometimes longer), everyone sees the same result and the world makes sense again.</p><p>Consistency, then, isn&#8217;t about rigidly enforcing one absolute truth at all times; it&#8217;s about <strong>ensuring the truth isn&#8217;t lost and will be shared</strong>. It&#8217;s a promise that the system, given enough time and correct mechanisms, can line up all its pieces of truth into a coherent whole. And it&#8217;s a reminder that sometimes patience (waiting for things to sync up) and clever design (hiding the waiting, ordering updates) can achieve the best of both worlds &#8211; a system that feels fast and fluid for users, yet still converges on correctness behind the scenes.</p><h1>&#9997;&#65039; Recap</h1><ul><li><p><strong>Consistency</strong> = agreement between nodes. All users or components see the same data, yielding a uniform view of the system. In distributed systems, achieving this often comes at the cost of speed or uptime.</p></li><li><p><strong>CAP theorem:</strong> In any distributed system, you can&#8217;t have all three of Consistency, Availability, and Partition tolerance at once. Because network partitions will happen, every design must choose which to prioritize (consistency vs. availability) when partitions occur.</p></li><li><p><strong>Many flavors of consistency:</strong> It&#8217;s not just &#8220;<em>consistent or not</em>&#8221;. There are multiple levels (strong, eventual, causal, read-your-writes, etc.), each defining how and when a system reaches agreement on updates. These models let us fine-tune the balance between immediacy and performance.</p></li><li><p><strong>Consistency vs. user experience:</strong> Great systems don&#8217;t necessarily enforce strict consistency everywhere &#8211; they just make the system <em>feel</em> consistent for users. Techniques like optimistic UI updates and careful UI cues (e.g. &#8220;<em>syncing</em>&#8221; indicators) hide the delays inherent in eventual consistency, so the user trusts what they see.</p></li><li><p><strong>Right tool for the job:</strong> Know when you truly need strong consistency (e.g. finance, medical, critical data) and when &#8220;<em>good enough</em>&#8221; will do. Often, relaxing consistency in non-critical areas yields huge gains in scalability and fault tolerance.</p></li><li><p><strong>Design for eventual consistency:</strong> Accept that temporary mismatches will occur and build your system to resolve them. Use <strong>reconciliation</strong> processes, <strong>conflict resolution</strong> strategies, and clear client guarantees (like read-your-writes) to manage inconsistencies. This isn&#8217;t a weakness &#8211; it&#8217;s a wise design strategy that acknowledges reality.</p></li></ul><div><hr></div><div class="poll-embed" data-attrs="{&quot;id&quot;:412222}" data-component-name="PollToDOM"></div><div><hr></div><p>In summary, consistency isn&#8217;t a black-or-white property but a nuanced aspect of system design. The goal is to ensure the system can eventually align on a single source of truth and, in the meantime, keep things running smoothly. By understanding the shades of consistency and learning how to mask or manage inconsistency, we can build distributed systems that are both <strong>reliable</strong> and <strong>user-friendly</strong> &#8211; systems that don&#8217;t always have to be perfectly consistent every split-second, as long as they get there when it counts.</p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p><a href="https://www.splunk.com/en_us/blog/learn/cap-theorem.html">CAP Theorem &amp; Strategies for Distributed Systems</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p><a href="https://arpitbhayani.me/blogs/eventual-consistency">Why Eventual Consistency is Preferred in Distributed Systems</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p><a href="https://www.usenix.org/system/files/login/articles/08_lloyd_41-43_online.pdf">A Short Primer on Causal Consistency</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-4" href="#footnote-anchor-4" class="footnote-number" contenteditable="false" target="_self">4</a><div class="footnote-content"><p><a href="https://blog.algomaster.io/p/strong-vs-eventual-consistency">Strong vs. Eventual Consistency</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-5" href="#footnote-anchor-5" class="footnote-number" contenteditable="false" target="_self">5</a><div class="footnote-content"><p><a href="https://shivangsnewsletter.com/p/understanding-database-consistency">Understanding Database Consistency Levels And Applying Them To A Single Web Service</a></p></div></div>]]></content:encoded></item><item><title><![CDATA[How systems handle failure — retries, circuit breakers, and idempotency]]></title><description><![CDATA[System design fundamentals]]></description><link>https://iam.slys.dev/p/how-systems-handle-failure-retries</link><guid isPermaLink="false">https://iam.slys.dev/p/how-systems-handle-failure-retries</guid><dc:creator><![CDATA[Jakub Slys 🤖]]></dc:creator><pubDate>Tue, 18 Nov 2025 20:32:13 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!YsF7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc1b310c-63e4-4a2e-8bd4-28aba7fcf91a_1536x1024.jpeg" 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_!YsF7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc1b310c-63e4-4a2e-8bd4-28aba7fcf91a_1536x1024.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YsF7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc1b310c-63e4-4a2e-8bd4-28aba7fcf91a_1536x1024.jpeg 424w, https://substackcdn.com/image/fetch/$s_!YsF7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc1b310c-63e4-4a2e-8bd4-28aba7fcf91a_1536x1024.jpeg 848w, https://substackcdn.com/image/fetch/$s_!YsF7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc1b310c-63e4-4a2e-8bd4-28aba7fcf91a_1536x1024.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!YsF7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc1b310c-63e4-4a2e-8bd4-28aba7fcf91a_1536x1024.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YsF7!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc1b310c-63e4-4a2e-8bd4-28aba7fcf91a_1536x1024.jpeg" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cc1b310c-63e4-4a2e-8bd4-28aba7fcf91a_1536x1024.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:213463,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176729895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc1b310c-63e4-4a2e-8bd4-28aba7fcf91a_1536x1024.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!YsF7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc1b310c-63e4-4a2e-8bd4-28aba7fcf91a_1536x1024.jpeg 424w, https://substackcdn.com/image/fetch/$s_!YsF7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc1b310c-63e4-4a2e-8bd4-28aba7fcf91a_1536x1024.jpeg 848w, https://substackcdn.com/image/fetch/$s_!YsF7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc1b310c-63e4-4a2e-8bd4-28aba7fcf91a_1536x1024.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!YsF7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc1b310c-63e4-4a2e-8bd4-28aba7fcf91a_1536x1024.jpeg 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 role="img" 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><title></title><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><blockquote><p><strong>You click &#8220;Buy Now&#8221;.</strong><br>The spinner turns&#8230; and turns&#8230; and then disappears.<br>You check your bank app - payment went through.<br>But the website shows: <em>&#8220;Error - please try again&#8221;.</em></p><p>Congratulations. You&#8217;ve just met the gray zone of distributed systems -<br>where a single operation might have succeeded, failed, or both.</p></blockquote><p>Welcome to the world where software fails in confusing ways. In distributed systems, it&#8217;s possible for an action (like a payment) to <strong>actually succeed</strong> on the backend while the frontend thinks it failed. The result? Confusion, duplicate charges, and frustrated users. This scenario isn&#8217;t just a bad day for you; it&#8217;s a reality that <strong>reliable systems must handle gracefully</strong>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!W2fx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3d39dec-790a-44c6-8f12-e67e61f6849c_1324x918.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!W2fx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3d39dec-790a-44c6-8f12-e67e61f6849c_1324x918.jpeg 424w, https://substackcdn.com/image/fetch/$s_!W2fx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3d39dec-790a-44c6-8f12-e67e61f6849c_1324x918.jpeg 848w, https://substackcdn.com/image/fetch/$s_!W2fx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3d39dec-790a-44c6-8f12-e67e61f6849c_1324x918.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!W2fx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3d39dec-790a-44c6-8f12-e67e61f6849c_1324x918.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!W2fx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3d39dec-790a-44c6-8f12-e67e61f6849c_1324x918.jpeg" width="1324" height="918" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c3d39dec-790a-44c6-8f12-e67e61f6849c_1324x918.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:918,&quot;width&quot;:1324,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:88112,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176729895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3d39dec-790a-44c6-8f12-e67e61f6849c_1324x918.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!W2fx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3d39dec-790a-44c6-8f12-e67e61f6849c_1324x918.jpeg 424w, https://substackcdn.com/image/fetch/$s_!W2fx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3d39dec-790a-44c6-8f12-e67e61f6849c_1324x918.jpeg 848w, https://substackcdn.com/image/fetch/$s_!W2fx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3d39dec-790a-44c6-8f12-e67e61f6849c_1324x918.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!W2fx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3d39dec-790a-44c6-8f12-e67e61f6849c_1324x918.jpeg 1456w" sizes="100vw"></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 role="img" 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><title></title><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>In this post, we&#8217;ll explore how modern systems <strong>embrace failure</strong> without hurting the user experience. We&#8217;ll demystify how <strong>retries</strong>, <strong>circuit breakers</strong>, and <strong>idempotency</strong> work together so that even when things go wrong, they go <em>right</em>. By the end, you&#8217;ll see why resilient software doesn&#8217;t fear failure - it expects it, plans for it, and bounces back before anyone even notices.</p><div><hr></div><p><strong>&#128161; Before we go deeper - if you&#8217;re enjoying posts like this, consider subscribing to my publication.</strong><br>I write about system design, architecture, AI, reliability, and the &#8220;<em>behind-the-scenes</em>&#8221; stuff that helps you grow as a developer.</p><p>Subscribing means you won&#8217;t miss new breakdowns, diagrams, or hands-on explanations - and it genuinely helps me keep creating more content like this for you.</p><p><strong>Join in if you want to learn this stuff together. &#128640;</strong></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h1>&#9881;&#65039; Failure is normal in distributed systems</h1><p>In a distributed system, <strong>failure is not an exception - it&#8217;s normal</strong>. Networks drop packets. Services time out. Messages can arrive twice (or not at all). Servers might restart right in the middle of a transaction. Yet users still expect the system to &#8220;<em>just work</em>&#8221; smoothly despite all that chaos happening behind the scenes.</p><p>Why so much chaos? Because once you have many components interacting over a network, the unlikely becomes likely. A hardware failure that&#8217;s rare on one machine becomes <strong>common when you have thousands<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></strong>. A &#8220;<em>once in a million</em>&#8221; glitch might occur a few times a day across a global fleet of servers. As a classic principle of cloud computing states: <em>&#8220;In distributed systems, failure is normal&#8230; failures are assumed, designs work around them, and software anticipates them&#8221;.</em></p><p>The key insight is this:</p><p>&#10145;&#65039; <strong>Reliability isn&#8217;t about avoiding failure; it&#8217;s about making failure uneventful.</strong> In other words, a well-designed system experiences faults all the time, but it handles them so gracefully that nobody notices. Instead of treating failures as catastrophic anomalies, resilient systems treat them as expected events and have <strong>built-in responses</strong>. Just like a car has shock absorbers for bumps in the road, distributed software has patterns to absorb the shocks of downtime, lost messages, and random errors.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!lYOZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38aec2d6-066a-4e79-97bf-760755b73c53_1440x1191.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lYOZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38aec2d6-066a-4e79-97bf-760755b73c53_1440x1191.jpeg 424w, https://substackcdn.com/image/fetch/$s_!lYOZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38aec2d6-066a-4e79-97bf-760755b73c53_1440x1191.jpeg 848w, https://substackcdn.com/image/fetch/$s_!lYOZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38aec2d6-066a-4e79-97bf-760755b73c53_1440x1191.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!lYOZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38aec2d6-066a-4e79-97bf-760755b73c53_1440x1191.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!lYOZ!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38aec2d6-066a-4e79-97bf-760755b73c53_1440x1191.jpeg" width="1200" height="992.5" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/38aec2d6-066a-4e79-97bf-760755b73c53_1440x1191.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1191,&quot;width&quot;:1440,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:124594,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176729895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38aec2d6-066a-4e79-97bf-760755b73c53_1440x1191.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!lYOZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38aec2d6-066a-4e79-97bf-760755b73c53_1440x1191.jpeg 424w, https://substackcdn.com/image/fetch/$s_!lYOZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38aec2d6-066a-4e79-97bf-760755b73c53_1440x1191.jpeg 848w, https://substackcdn.com/image/fetch/$s_!lYOZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38aec2d6-066a-4e79-97bf-760755b73c53_1440x1191.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!lYOZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38aec2d6-066a-4e79-97bf-760755b73c53_1440x1191.jpeg 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 role="img" 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><title></title><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>So, the mindset shift is crucial: <strong>don&#8217;t panic when things go wrong - plan for it.</strong> The next sections will cover exactly how to plan for failures using retries, circuit breakers, and idempotency so that even when something breaks, your application <em>bends without breaking</em>.</p><h1>&#128257; The first line of defense &#8212; retries</h1><p>When an operation fails transiently (say, a network request times out), often the simplest fix is: <strong>try again</strong>. This is the idea of <strong>retries</strong> &#8211; automatically attempting an operation again in hopes that a momentary glitch resolves. In many cases, a quick retry turns a failure into a success: the network hiccup passes, the second call reaches the server, and all is well. In fact, retries are a major reason distributed systems can mask inevitable flakiness and still meet high uptime goals<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a>.</p><p>However, retries are a double-edged sword. If used naively, they can <strong>make things worse</strong> instead of better.</p><p><strong>Retry storms and overload.</strong> If a service is truly down or overloaded, blind retries from many clients can create a <em>stampede</em>. Imagine hundreds of clients all retrying failed requests at the same time &#8211; the failing service gets bombarded with even more traffic just when it&#8217;s least able to handle it. This feedback loop is known as a <strong>retry storm</strong>, and it can turn a small outage into a cascade of failures. In one scenario, a failure in a deep call chain caused a 2^N explosion of retries, overwhelming the database and prolonging the outage. In short, retries are &#8220;<em>selfish</em>&#8221; - each client is just trying to succeed, but collectively they can hammer the server<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a>.</p><p><strong>Duplicate actions.</strong> Retrying an operation that actually <em>did</em> go through can trigger duplicate effects. For example, if the first &#8220;<em>Buy Now</em>&#8221; <em>did</em> charge your card but the acknowledgement got lost, a retry might charge you again. Without precautions, you could end up with two payments, two created accounts, or duplicate messages. In technical terms, <strong>at-least-once delivery</strong> means the same action might happen twice. (Ever gotten two confirmation emails for one order? That&#8217;s a duplicate caused by a retry.) Unless the system is built to handle this, a single user action could be processed multiple times<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a>.</p><p><strong>How do we retry safely?</strong> The answer is controlled retries, using techniques like <strong>exponential backoff</strong> and <strong>jitter</strong>.</p><p><strong>Exponential Backoff.</strong> Instead of retrying immediately at a constant rate, exponential backoff waits progressively longer between attempts. For example, wait 1 second before the first retry, 2 seconds before the next, then 4 seconds, then 8, and so on. This gives the failing service time to recover and prevents slamming it with rapid-fire calls. It&#8217;s like knocking on a door: if no one answers, you wait a bit longer before knocking again. This pattern is extremely common for handling transient failures gracefully<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a>.</p><p><strong>Jitter (Random Delay).</strong> A big problem is when many clients retry in sync &#8211; even with backoff, if they all wait 1, 2, 4, 8 seconds, they&#8217;ll still line up and hit at once. <strong>Jitter</strong> introduces randomness to break the synchronization. For instance, if backoff says &#8220;<em>wait 2 seconds</em>&#8221;, each client actually waits a random time up to 2 seconds (maybe one waits 1.7s, another 2.3s). This <strong>spreads out the retries</strong> and avoids a thundering herd. Jitter is like adding a small random delay to your next knock on the door, so that a whole crowd of people won&#8217;t all knock in unison.</p><p>With <strong>exponential backoff and jitter</strong>, retries become polite and <em>intelligent</em>. They exponentially decrease the retry rate under duress and randomize the timing so that servers aren&#8217;t overwhelmed. Most cloud SDKs and HTTP clients implement these patterns by default (e.g., the AWS SDK uses capped exponential backoff with jitter to protect services).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YJdP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b7019fc-0c0a-420e-9a10-6be3b495bb9f_1498x665.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YJdP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b7019fc-0c0a-420e-9a10-6be3b495bb9f_1498x665.jpeg 424w, https://substackcdn.com/image/fetch/$s_!YJdP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b7019fc-0c0a-420e-9a10-6be3b495bb9f_1498x665.jpeg 848w, https://substackcdn.com/image/fetch/$s_!YJdP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b7019fc-0c0a-420e-9a10-6be3b495bb9f_1498x665.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!YJdP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b7019fc-0c0a-420e-9a10-6be3b495bb9f_1498x665.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YJdP!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b7019fc-0c0a-420e-9a10-6be3b495bb9f_1498x665.jpeg" width="1200" height="532.4175824175824" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6b7019fc-0c0a-420e-9a10-6be3b495bb9f_1498x665.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:646,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:84782,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176729895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b7019fc-0c0a-420e-9a10-6be3b495bb9f_1498x665.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!YJdP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b7019fc-0c0a-420e-9a10-6be3b495bb9f_1498x665.jpeg 424w, https://substackcdn.com/image/fetch/$s_!YJdP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b7019fc-0c0a-420e-9a10-6be3b495bb9f_1498x665.jpeg 848w, https://substackcdn.com/image/fetch/$s_!YJdP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b7019fc-0c0a-420e-9a10-6be3b495bb9f_1498x665.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!YJdP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b7019fc-0c0a-420e-9a10-6be3b495bb9f_1498x665.jpeg 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 role="img" 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><title></title><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>Finally, it&#8217;s critical to <strong>limit retries</strong>. Have a maximum number of attempts or a total timeout budget. Unbounded retries can loop forever or until the system collapses &#8211; definitely an anti-pattern. Many systems also <strong>differentiate errors</strong>: for example, do not retry on a 400 Bad Request (the request is invalid and won&#8217;t magically succeed later). Save retries for the <em>maybe-fixable</em> errors like timeouts, 5xx server errors, or network glitches.</p><blockquote><p><strong>Metaphor:</strong> Don&#8217;t shout the same question every second to someone who didn&#8217;t hear you. If you get silence or a muffled answer, pause. Wait a bit longer each time, and try again &#8211; <strong>gently</strong>. By raising your voice gradually and adding a random pause, you avoid becoming part of a chaotic shouting chorus.</p></blockquote><h1>&#9889; Circuit breaker &#8212; knowing when to stop trying</h1><p>If retries are the first line of defense, the <strong>circuit breaker</strong> pattern is the emergency stop. Sometimes the most resilient thing you can do is <strong>stop</strong> calling a failing service and give it time to heal. A circuit breaker in software plays a similar role to one in your house&#8217;s electrical panel: when too many failures occur, it &#8220;<em>trips</em>&#8221; to prevent further damage.</p><p>Imagine a downstream service that has been timing out for dozens of requests in a row. Instead of blindly retrying again and again, a smart client will <strong>flip the circuit open</strong>: it refuses to send more requests for a short period. This prevents wasting resources on doomed attempts and stops adding load to a service that&#8217;s already in trouble. As Martin Fowler put it, without circuit breakers a chain of failures can consume critical resources and lead to a <strong>cascading collapse</strong> of multiple systems<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-6" href="#footnote-6" target="_self">6</a>. The circuit breaker breaks the chain.</p><p>A typical software circuit breaker has three states:</p><ol><li><p><strong>Closed (normal operation):</strong> Everything is working, so the circuit is closed and calls flow normally. The client keeps a <strong>failure count</strong>. As long as calls succeed (or failures stay below a threshold), the breaker remains closed. It&#8217;s like the switch is &#8220;<em>on</em>&#8221; allowing electricity (requests) through.</p></li><li><p><strong>Open (tripped):</strong> After a certain number of failures in a row (say 5 failures within a minute), the breaker &#8220;<em>trips</em>&#8221; open. In the Open state, <strong>no calls are made at all</strong> - the client fails fast, immediately returning an error or fallback response without even attempting the operation. It&#8217;s as if the switch is &#8220;<em>off</em>&#8221; - requests get short-circuited. The open state usually lasts for a predefined timeout interval. The idea is to <strong>stop hammering the failing service</strong> and give it a break<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-7" href="#footnote-7" target="_self">7</a>.</p></li><li><p><strong>Half-open (probe/test):</strong> After the open timeout expires, the circuit goes half-open. In this state, the client will <strong>allow a limited number of test requests</strong> to see if the service has recovered. It&#8217;s like cautiously closing the circuit just a little to test the waters. If a test request succeeds, that&#8217;s a good sign - the breaker may reset to Closed (fully close the circuit) and resume normal operations, resetting the failure counter. If a test request fails, the breaker snaps back to Open and the timeout period starts over. This prevents a flapping service from getting flooded immediately as it comes back online.</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_!sczj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F813748a5-3353-4ee5-99ba-1941f234e06c_1375x590.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!sczj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F813748a5-3353-4ee5-99ba-1941f234e06c_1375x590.jpeg 424w, https://substackcdn.com/image/fetch/$s_!sczj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F813748a5-3353-4ee5-99ba-1941f234e06c_1375x590.jpeg 848w, https://substackcdn.com/image/fetch/$s_!sczj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F813748a5-3353-4ee5-99ba-1941f234e06c_1375x590.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!sczj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F813748a5-3353-4ee5-99ba-1941f234e06c_1375x590.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!sczj!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F813748a5-3353-4ee5-99ba-1941f234e06c_1375x590.jpeg" width="1200" height="514.9090909090909" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/813748a5-3353-4ee5-99ba-1941f234e06c_1375x590.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:590,&quot;width&quot;:1375,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:58040,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176729895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F813748a5-3353-4ee5-99ba-1941f234e06c_1375x590.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!sczj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F813748a5-3353-4ee5-99ba-1941f234e06c_1375x590.jpeg 424w, https://substackcdn.com/image/fetch/$s_!sczj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F813748a5-3353-4ee5-99ba-1941f234e06c_1375x590.jpeg 848w, https://substackcdn.com/image/fetch/$s_!sczj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F813748a5-3353-4ee5-99ba-1941f234e06c_1375x590.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!sczj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F813748a5-3353-4ee5-99ba-1941f234e06c_1375x590.jpeg 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 role="img" 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><title></title><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>These states and transitions ensure that once a service starts consistently failing, we <strong>stop persistent retries</strong> (which were just hurting) and periodically check if it&#8217;s okay again. The pattern improves overall <strong>stability and responsiveness</strong> - clients don&#8217;t hang waiting for timeouts on every request when the service is known to be down; they fail fast or fall back to a default behavior. Meanwhile, the failing component gets breathing room to recover instead of being DDoS&#8217;ed by its own clients.</p><blockquote><p><strong>Metaphor:</strong> The circuit breaker is like a friend who says: <em>&#8220;They&#8217;re not answering and must be overwhelmed. Let&#8217;s stop calling them for a while - they clearly need time to recover.&#8221;</em> It&#8217;s the voice of reason that prevents you from redialing a number 100 times in a minute. Only after a pause will your friend say, <em>&#8220;Okay, try again now and see if they pick up.&#8221;</em> If they do, great! If not, wait a bit longer and try later.</p></blockquote><p>The insight here is that <strong>persistence without awareness isn&#8217;t resilience - it&#8217;s self-sabotage</strong>. A robust system needs to know when to <strong>quit</strong> and when to <strong>retry</strong>. Circuit breakers add that awareness by monitoring error rates. They essentially enforce the rule: <em>&#8220;Don&#8217;t keep doing the same failing thing over and over&#8221;.</em> Instead, fail fast and handle it gracefully (perhaps return a cached response or a friendly error to the user), and try again later when there&#8217;s a chance of success.</p><p>Most modern frameworks and libraries have circuit breaker implementations (<em>Netflix&#8217;s Hystrix</em> popularized this, and tools like <em>Resilience4j</em> in Java or <em>Polly</em> in .NET provide them). They typically allow configuration of the failure threshold, open-state timeout, and half-open trial settings. Additionally, breakers often work in tandem with retries: e.g., you might retry a few times on an error, but if failures persist, open the circuit. In fact, <strong>combining Retries + Circuit Breaker</strong> is common &#8211; retry a transient error, but if errors keep happening, stop trying for a bit.</p><h1>&#129518; Idempotency &#8212; doing the same thing twice without breaking anything</h1><p>Retries and circuit breakers help manage <em>when</em> and <em>how</em> to repeat operations safely. But there&#8217;s a deeper prerequisite for safe retries: the operation itself must be <strong>safe to repeat</strong>. This is where <strong>idempotency</strong> comes in.</p><p>An operation is <strong>idempotent</strong> if performing it multiple times has the <strong>same effect</strong> as doing it once. If you send the same request twice, an idempotent service will not create a mess or unintended side effects. The classic example: <strong>setting a value vs. incrementing a value</strong>.</p><p><strong>Idempotent example:</strong> &#8220;<em>Set user&#8217;s balance to $100</em>&#8221;. Do it once, the balance is $100. Do it five times, the balance is still $100. No harm in the repeats.</p><p><strong>Non-idempotent example:</strong> &#8220;<em>Add $100 to user&#8217;s balance</em>&#8221;. Do it once, balance increases by $100. Do it five times (accidentally), and you&#8217;ve added $500 - likely not what you intended!</p><p>In formal terms, <em>if </em><code>f(x)</code><em> is an idempotent operation, then </em><code>f(f(x)) = f(x)</code>. The outcome doesn&#8217;t change after the first application. <strong>Repeating it doesn&#8217;t amplify the effect</strong>.</p><p>Why is this so crucial? Because in distributed systems, you <strong>often can&#8217;t be sure if a request succeeded or not</strong>, so you may need to retry - and that retry should not cause bad side effects. If an operation is not idempotent, even a single retry can produce incorrect results. Think of charging a credit card, sending an email, or creating a user account - if those actions are duplicated, you get double charges, duplicate emails, or multiple accounts for the same user. Not good.</p><p><strong>Key idea:</strong> Retries are safe <em>only if</em> the operation is idempotent (or the system has other ways to avoid double-processing). This is why many APIs that involve side effects are designed to be idempotent or provide idempotency mechanisms. For instance, HTTP <strong>GET</strong> is by definition idempotent (it&#8217;s just a read), and HTTP <strong>PUT</strong> is generally designed to be idempotent (replace resource state), whereas <strong>POST</strong> often is not (create a new resource, which if repeated creates duplicates).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!u1u_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6df25c67-953e-4230-8d04-6bcdcfdd1a10_1262x1205.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!u1u_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6df25c67-953e-4230-8d04-6bcdcfdd1a10_1262x1205.jpeg 424w, https://substackcdn.com/image/fetch/$s_!u1u_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6df25c67-953e-4230-8d04-6bcdcfdd1a10_1262x1205.jpeg 848w, https://substackcdn.com/image/fetch/$s_!u1u_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6df25c67-953e-4230-8d04-6bcdcfdd1a10_1262x1205.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!u1u_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6df25c67-953e-4230-8d04-6bcdcfdd1a10_1262x1205.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!u1u_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6df25c67-953e-4230-8d04-6bcdcfdd1a10_1262x1205.jpeg" width="728" height="695.1188589540412" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6df25c67-953e-4230-8d04-6bcdcfdd1a10_1262x1205.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:1205,&quot;width&quot;:1262,&quot;resizeWidth&quot;:728,&quot;bytes&quot;:134357,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176729895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6df25c67-953e-4230-8d04-6bcdcfdd1a10_1262x1205.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!u1u_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6df25c67-953e-4230-8d04-6bcdcfdd1a10_1262x1205.jpeg 424w, https://substackcdn.com/image/fetch/$s_!u1u_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6df25c67-953e-4230-8d04-6bcdcfdd1a10_1262x1205.jpeg 848w, https://substackcdn.com/image/fetch/$s_!u1u_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6df25c67-953e-4230-8d04-6bcdcfdd1a10_1262x1205.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!u1u_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6df25c67-953e-4230-8d04-6bcdcfdd1a10_1262x1205.jpeg 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 role="img" 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><title></title><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>So how do we achieve idempotency in practice? A few common techniques and patterns:</p><p><strong>Unique Request Identifiers (Idempotency keys):</strong> The client generates a unique token (say a UUID) for each logical operation and sends it with the request. The server keeps track of which tokens it has seen. If a duplicate request with the same token arrives (e.g., due to a retry), the server recognizes it and <strong>skips the duplicate action</strong>, or simply returns the same result as the original request without performing the action again<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-8" href="#footnote-8" target="_self">8</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-9" href="#footnote-9" target="_self">9</a>. For example, payment APIs (Stripe, PayPal, etc.) let you provide an idempotency key so that if the network flakes out after you hit &#8220;<em>Pay</em>&#8221;, you can safely retry with the same key and not charge the customer twice. AWS uses this approach widely - many AWS APIs (like EC2 instance creation) accept a client token, and if the same token is reused, AWS knows <em>&#8220;Ah, I&#8217;ve already handled this request&#8221;</em>. This shifts the ambiguity of &#8220;<em>did it succeed or not?</em>&#8221; into a clear record on the server side.</p><p><strong>Deduplication stores / logs:</strong> The server can record the outcome of operations in a database or log keyed by the operation&#8217;s unique ID. For example, a service might have a <code>processed_requests</code> table where it inserts the request ID when processing a transaction. If it receives the same ID again, it checks the table, sees it&#8217;s already processed, and aborts or returns the previous result<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-10" href="#footnote-10" target="_self">10</a>. This pattern is common in message processing: consumers keep track of message IDs they&#8217;ve seen to avoid processing the same message twice. The storage could be an in-memory cache, a SQL table, or even attaching identifiers to the resource created (like tagging a database entry with the request ID that created it).</p><p><strong>Designing APIs for idempotency:</strong> Sometimes it&#8217;s as simple as choosing the right operation semantics. If you design an API call as &#8220;<em><strong>create or return existing</strong></em>&#8221; (like a put-if-absent), it can be made idempotent. For instance, an API might treat duplicate create requests as a no-op after the first time. Another approach is using <strong>PUT vs. POST</strong> semantics: e.g., <code>PUT /orders/{id}</code> with the same order ID can be made to either create the order if not exists or return the existing one if it does, ensuring that retrying the PUT doesn&#8217;t create multiple orders. Good API design encourages making operations idempotent whenever possible. In fact, one of Amazon&#8217;s best practices is: <em>&#8220;design APIs to be idempotent, meaning they can be safely retried&#8221;.</em></p><p><strong>Potency by &#8220;</strong><em><strong>Replace</strong></em><strong>&#8221; Instead of &#8220;</strong><em><strong>Add</strong></em><strong>&#8221;:</strong> As mentioned, structure operations as <strong>set to a value</strong> rather than <strong>add a value</strong>, or <strong>idempotent upsert</strong> instead of insert. For example, if an event says &#8220;<em>user paid $100 on order #123</em>&#8221;, record that specific event once rather than something like &#8220;<em>increase balance by 100</em>&#8221; which can&#8217;t be repeated. In databases, use <strong>UPSERT</strong> (update-or-insert) so that applying the same record twice results in one record (updated) not duplicates. Idempotent design often requires thinking in terms of final state (&#8220;<em>ensure it ends up like this</em>&#8221;) rather than one-time actions (&#8220;<em>do this once</em>&#8221;).</p><p>It&#8217;s worth noting that idempotency sometimes requires <strong>extra work</strong> on the backend - keeping logs of request IDs, handling more complex logic - but it <em>significantly improves reliability</em>. It removes ambiguity. In our initial story, the reason it&#8217;s a gray zone is because the system wasn&#8217;t fully idempotent from the user&#8217;s perspective. The payment went through (state changed) but the website didn&#8217;t see the result, and it couldn&#8217;t safely retry the exact operation without risking a double charge. With an idempotent design (say the site had sent a charge request with an idempotency key), the client could retry the charge call safely - the payment service would say &#8220;<em>I already did that, here&#8217;s the result, no double charge</em>&#8221;.</p><blockquote><p><strong>Metaphor:</strong> Idempotency is like saying, <em>&#8220;I already told you once - doing it again shouldn&#8217;t change the outcome&#8221;.</em> If you ask a friend to turn off the light, and they did it, asking again won&#8217;t plunge the room into <em>double</em> darkness - it&#8217;s just off. But if you asked them to &#8220;<em>turn the dimmer down by 20%</em>&#8221;, asking twice would make it twice as dark. Idempotency is preferring the first style of request (&#8220;<em>set it to this state</em>&#8221;) so that repeating the request doesn&#8217;t cause chaos.</p></blockquote><p>Before we move on, an important link: <strong>Idempotency + Retries + Circuit Breakers</strong> all dance together. Idempotency makes retries safe, and circuit breakers stop futile retries from overwhelming anyone. In the next section, we&#8217;ll see how these patterns combine to create a system that can <em>heal itself</em> in the face of failure.</p><h2>&#129504; Putting it together &#8212; a system that heals itself</h2><p>Let&#8217;s walk through a failure scenario and see how <strong>retries, circuit breakers, and idempotency complement each other</strong> to save the day:</p><p><strong>Scenario:</strong> You have a service <code>A</code> (perhaps a frontend service) that calls service <code>B</code> (say, a payment service). A user initiates an action that triggers <code>A -&gt; B</code> call.</p><ul><li><p><strong>Step 1: Initial failure and retry.</strong> Service B doesn&#8217;t respond (maybe it&#8217;s slow or temporarily down). Service A&#8217;s request to B <strong>times out</strong>. Now, A doesn&#8217;t immediately give up; it knows this could be a transient fault. Thanks to a retry policy, A <em>retries the request</em> to B after, say, 1 second. Importantly, the operation is designed to be <strong>idempotent</strong> - perhaps it includes a unique transaction ID for this payment. Therefore, if B actually got the first request and processed it, the second request will be recognized as a duplicate and ignored (or B will return the previous result). If the first request never hit B, then the retry is truly needed. Either way, retrying won&#8217;t cause a double effect. The retry gives B a second chance to do the work, in case the issue was a fluke.</p></li><li><p><strong>Step 2: Multiple failures and circuit open.</strong> Unfortunately, service B is having a bad time - it&#8217;s still unresponsive on the retry attempt. A times out again. At this point, our retry policy might attempt again with exponential backoff (wait 2 seconds, try again). Let&#8217;s say we try a couple of times, but all attempts within a short window keep failing. Now the <strong>circuit breaker</strong> logic kicks in: after, say, 3 failed tries in a row, A&#8217;s circuit breaker for calls to B <strong>trips open</strong>. This means <em>for the next 30 seconds, A will not send any requests to B at all</em>. Any user actions that would call B immediately get a failure or fallback response. This sounds harsh, but it prevents A from continuously piling requests onto B when B is definitely down. It&#8217;s containing the damage. Users might get a quick error message like &#8220;<em>Service unavailable, please try after some time</em>&#8221; <em>immediately</em> rather than staring at spinners that will inevitably timeout. Meanwhile, B gets a breather without traffic.</p></li><li><p><strong>Step 3: Self-healing test (Half-open).</strong> After the cooldown period (30s) passes, A&#8217;s circuit breaker moves to <strong>half-open</strong>. It will now allow a <em>limited</em> test through - maybe it lets one or a few requests go to B instead of all of them. So the next user action triggers a real call to B. If B is still down and this call fails, the breaker snaps back to Open and the cycle repeats (wait longer). But suppose by now the team fixed B or it recovered on its own. That test request <strong>succeeds</strong>. Great! The circuit breaker takes this as a signal that B is healthy again. It transitions back to <strong>Closed</strong> state, resetting the failure count. Now A resumes normal operations and starts sending all requests to B again.</p></li><li><p><strong>Step 4: Graceful recovery and continuation.</strong> Traffic flows normally; the system healed itself. Users maybe noticed a brief hiccup, but the system didn&#8217;t meltdown. If idempotency keys were in play, any retried operations during the half-open testing are safe and don&#8217;t double-execute. If some actions couldn&#8217;t be completed while the circuit was open, perhaps A queued them or returned an error that the user can retry. But importantly, when B came back, it wasn&#8217;t immediately crushed by a thundering herd, because the circuit breaker let only a trickle of requests through to confirm health before fully opening the gates.</p></li></ul><p>Throughout this dance, <strong>observability</strong> (which we&#8217;ll discuss next) would be tracking what&#8217;s happening: metrics like &#8220;<em>how many retries occurred</em>&#8221; or &#8220;<em>is the circuit breaker open right now</em>&#8221; would alert engineers that B was failing and recovering.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WNBS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2693d111-c9df-44c3-b59b-9b65a4198d89_1503x939.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WNBS!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2693d111-c9df-44c3-b59b-9b65a4198d89_1503x939.jpeg 424w, https://substackcdn.com/image/fetch/$s_!WNBS!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2693d111-c9df-44c3-b59b-9b65a4198d89_1503x939.jpeg 848w, https://substackcdn.com/image/fetch/$s_!WNBS!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2693d111-c9df-44c3-b59b-9b65a4198d89_1503x939.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!WNBS!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2693d111-c9df-44c3-b59b-9b65a4198d89_1503x939.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WNBS!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2693d111-c9df-44c3-b59b-9b65a4198d89_1503x939.jpeg" width="1200" height="750" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2693d111-c9df-44c3-b59b-9b65a4198d89_1503x939.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:910,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:109018,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176729895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2693d111-c9df-44c3-b59b-9b65a4198d89_1503x939.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!WNBS!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2693d111-c9df-44c3-b59b-9b65a4198d89_1503x939.jpeg 424w, https://substackcdn.com/image/fetch/$s_!WNBS!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2693d111-c9df-44c3-b59b-9b65a4198d89_1503x939.jpeg 848w, https://substackcdn.com/image/fetch/$s_!WNBS!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2693d111-c9df-44c3-b59b-9b65a4198d89_1503x939.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!WNBS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2693d111-c9df-44c3-b59b-9b65a4198d89_1503x939.jpeg 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 role="img" 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><title></title><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>Insight:</strong> Resilient systems aren&#8217;t perfect; they <em>expect</em> things to break. The magic is in <strong>how they fail</strong>:</p><ul><li><p>They <em>fail fast</em> when needed (circuit open),</p></li><li><p>They <em>retry calmly</em> when it&#8217;s worth it (controlled retries with backoff),</p></li><li><p>They <em>avoid dangerous side effects</em> (idempotent operations),</p></li><li><p>And they <em>recover automatically</em> (circuit half-open to closed transition).</p></li></ul><p>In essence, the system &#8220;<em>takes a deep breath</em>&#8221; during an outage: it stops pressing on the broken part, waits a bit, tries again carefully, and then continues as normal. This is often referred to as <strong>graceful degradation</strong> and self-healing. Users might see slightly slower responses or a friendly error message, but not a catastrophic failure or inconsistent data.</p><blockquote><p><strong>Real-world example:</strong> Netflix (which pioneered a lot of these patterns) will show you older cached content or a &#8220;<em>Netflix is temporarily unavailable</em>&#8221; screen rather than just crash, if its backend services are failing. After a few seconds, it will transparently retry connecting. You, as the user, are only mildly inconvenienced instead of being completely unable to use the service.</p></blockquote><h1>&#129513; Observability &#8212; seeing failures before users do</h1><p>All these resilience patterns (retries, breakers, idempotency) work best when you can <strong>see what&#8217;s happening inside your system</strong>. That&#8217;s where <strong>observability</strong> comes in. Observability means having the right data (logs, metrics, traces) to understand the system&#8217;s behavior and catch issues early. It&#8217;s the <strong>nervous system</strong> of your software that lets you sense trouble and react before users are impacted.</p><p><strong>You can&#8217;t fix what you can&#8217;t see.</strong> Instrument your system to track the crucial signals:</p><ul><li><p><strong>Metrics:</strong> Define and watch metrics that relate to reliability. For example:</p><ul><li><p><strong>Retry counts and rates</strong> - how often are retries happening? A spike in retries might mean a downstream service is flaking out.</p></li><li><p><strong>Circuit breaker state</strong> - expose whether the circuit is open, half-open, or closed, and count how many times it opens. If a circuit breaker is tripping frequently, something is wrong downstream (or your threshold is too sensitive).</p></li><li><p><strong>Error rates and latency</strong> - increased error percentage or slow responses can warn of impending failures (which might trigger retries or breaker trips).</p></li><li><p><strong>Idempotency rejections or duplicates</strong> - if you track how many duplicate requests were detected and suppressed, it could indicate clients are retrying a lot (or misbehaving).</p></li></ul><p>Use tools like <em>Prometheus</em> or <em>CloudWatch</em> to collect these metrics. Set up <strong>alerts</strong> when thresholds are breached (e.g., alert if circuit opens more than X times in an hour, or if retry rate &gt; Y%). A well-tuned alert can notify you of a failing dependency <em>before</em> users start calling support.</p></li><li><p><strong>Logging with context (Correlation IDs):</strong> When errors do occur, logs are invaluable for debugging - but only if you can trace what happened. Implement <strong>correlation IDs</strong> (also called trace IDs) that flow through your system: from the user request through all the microservices it touches. By logging the ID with every error or important event, you can reconstruct the path of a request. For instance, if a user&#8217;s payment failed after 3 retries, you&#8217;d see one correlation ID with logs from service A&#8217;s retries, and maybe logs in service B if it was reached. Structured logs (JSON logs with key fields like <code>requestId</code>, <code>userId</code>, etc.) make it easier to filter and search. As an example, a log entry might contain <code>correlationId: abc-123</code> along with an error message &#8211; using that ID you pull all related logs across services. This way, when something goes wrong, you don&#8217;t have a needle in a haystack; you have a thread to pull.</p></li><li><p><strong>Distributed Tracing:</strong> Traces are like an x-ray of how a single transaction flows through multiple services. Tools like <em><strong>OpenTelemetry</strong></em> (with <em>Jaeger</em>, <em>Zipkin</em>, etc.) allow you to capture timings and causality: e.g., Service A called B, which called C. If a request is slow or fails, a trace can pinpoint where. Maybe 95% of the time was spent waiting on a database call in service C, or maybe service B had a 5-second pause. Tracing lets you visualize that call graph and timings. This is incredibly useful for failures that aren&#8217;t obvious - for example, a trace might reveal that your retries are all hitting the same instance of a service that is down, whereas if the load balancer sent one to a different instance it would work (maybe indicating you need smarter retry logic or that a whole zone is down). Many organizations sample traces and have dashboards to see error traces in near-real-time.</p></li><li><p><strong>Visualization &amp; Dashboards:</strong> Platforms like <em>Grafana</em> can chart your metrics over time - you might see a spike in &#8220;<em>retry_count</em>&#8221; or &#8220;<em>circuit_breaker_open{service=B}</em>&#8221; on a graph, correlating with a dip in throughput. Dashboards help connect the dots, and when an incident happens, you can quickly assess which part of the system is the bottleneck or failing.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fBBJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e824720-7c28-412f-bc48-1d04c9015c0d_1343x870.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fBBJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e824720-7c28-412f-bc48-1d04c9015c0d_1343x870.jpeg 424w, https://substackcdn.com/image/fetch/$s_!fBBJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e824720-7c28-412f-bc48-1d04c9015c0d_1343x870.jpeg 848w, https://substackcdn.com/image/fetch/$s_!fBBJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e824720-7c28-412f-bc48-1d04c9015c0d_1343x870.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!fBBJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e824720-7c28-412f-bc48-1d04c9015c0d_1343x870.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fBBJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e824720-7c28-412f-bc48-1d04c9015c0d_1343x870.jpeg" width="728" height="471.60089352196576" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9e824720-7c28-412f-bc48-1d04c9015c0d_1343x870.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:870,&quot;width&quot;:1343,&quot;resizeWidth&quot;:728,&quot;bytes&quot;:106607,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176729895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e824720-7c28-412f-bc48-1d04c9015c0d_1343x870.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!fBBJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e824720-7c28-412f-bc48-1d04c9015c0d_1343x870.jpeg 424w, https://substackcdn.com/image/fetch/$s_!fBBJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e824720-7c28-412f-bc48-1d04c9015c0d_1343x870.jpeg 848w, https://substackcdn.com/image/fetch/$s_!fBBJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e824720-7c28-412f-bc48-1d04c9015c0d_1343x870.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!fBBJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e824720-7c28-412f-bc48-1d04c9015c0d_1343x870.jpeg 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 role="img" 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><title></title><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>To sum up observability: <strong>collect, instrument, and monitor</strong> everything important. It&#8217;s not just for reacting, but proacting. If you notice a retry storm building or a database getting slower, you can intervene (maybe increase capacity or roll out a fix) <em>before</em> it full-on crashes. Observability is the difference between <em>randomly discovering failures when users scream</em> versus <em>detecting a problem at 3 AM and fixing it before the morning rush</em>.</p><blockquote><p>As a metaphor: Observability is the <strong>dashboard in your car</strong> with the check-engine lights and temperature gauges. You want to know if the engine is overheating <em>before</em> it explodes, and you want a speedometer to know if you&#8217;re going too fast around those reliability curves. Without a dashboard, you&#8217;re driving blind. Without software observability, you&#8217;re flying blind in production.</p></blockquote><p>In practice, implement basic monitoring on all these resilience mechanisms. Track how many times you are retrying, how long those retries wait, when circuits open/close, and any anomalies with duplicate request handling. Many libraries emit events for these (e.g., <em>Hystrix</em> had a stream of metrics you could tap into). Use that data to continually tune your thresholds too - maybe your circuit breaker is too sensitive (opening on one failure) or not sensitive enough (waiting until 100 failures). Observability guides those improvements.</p><div><hr></div><p><strong>&#128172; I&#8217;d really love to hear from you.</strong><br>What part of retry logic, circuit breakers, or idempotency clicked the most for you?</p><p>Or - what still feels confusing or &#8220;<em>magical</em>&#8221;?</p><p>Drop a comment below. I respond to everyone, and your questions often inspire new posts I wouldn&#8217;t have thought of on my own.</p><p>Don&#8217;t be shy - this is a friendly corner of the internet. &#128578;</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/how-systems-handle-failure-retries/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/how-systems-handle-failure-retries/comments"><span>Leave a comment</span></a></p><div><hr></div><h2>&#9878;&#65039; Failure design as a mindset</h2><p>Let&#8217;s step back from the technical details and talk philosophy. <strong>Building reliable systems isn&#8217;t about never making mistakes or preventing every failure.</strong> It&#8217;s about <strong>expecting failures</strong>, accepting that they <em>will</em> happen, and designing your system&#8217;s behavior in those moments so that nothing catastrophic occurs. In other words, <strong>embrace the chaos, but be ready for it</strong>.</p><p>Think of it this way: if you deploy code to thousands of servers, at any given time <em>something</em> is probably slightly broken. Hard drives crash, networks partition, a bug slips through. A novice might react with &#8220;<em>Oh no, everything must be 100% perfect or we&#8217;re doomed!</em>&#8221; But an expert mindset is, &#8220;<em>Failures will happen - let&#8217;s make sure when they do, it&#8217;s no big deal</em>&#8221;. This mindset shift is at the heart of Site Reliability Engineering (SRE) principles at companies like Google. They even intentionally introduce failures (chaos engineering) to test that their systems can handle them.</p><p>So, design for <strong>graceful failure</strong>. It&#8217;s an art:</p><ul><li><p><strong>Expect failures</strong>: Every external call might not return. Every write to disk might fail. Plan for it.</p></li><li><p><strong>Embrace them in testing</strong>: Simulate random outages or slowdowns and verify your system stays responsive (even if in degraded mode).</p></li><li><p><strong>Design recovery paths</strong>: As we&#8217;ve seen - wait, retry, timeout, failover, fallback. Always ask, &#8220;<em>If this part breaks, what will the user experience? Can we do better?</em>&#8221;</p></li><li><p><strong>Stay calm under pressure</strong>: A good system doesn&#8217;t panic when things break. It has that &#8220;<em>deep breath</em>&#8221; behavior we described. No frantic infinite loops or cascades, just controlled responses.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!DwK8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e9328f7-9410-4d3e-a7fc-9825f58075db_1397x670.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!DwK8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e9328f7-9410-4d3e-a7fc-9825f58075db_1397x670.jpeg 424w, https://substackcdn.com/image/fetch/$s_!DwK8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e9328f7-9410-4d3e-a7fc-9825f58075db_1397x670.jpeg 848w, https://substackcdn.com/image/fetch/$s_!DwK8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e9328f7-9410-4d3e-a7fc-9825f58075db_1397x670.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!DwK8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e9328f7-9410-4d3e-a7fc-9825f58075db_1397x670.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!DwK8!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e9328f7-9410-4d3e-a7fc-9825f58075db_1397x670.jpeg" width="1200" height="575.5189692197566" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1e9328f7-9410-4d3e-a7fc-9825f58075db_1397x670.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:670,&quot;width&quot;:1397,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:82914,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176729895?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e9328f7-9410-4d3e-a7fc-9825f58075db_1397x670.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!DwK8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e9328f7-9410-4d3e-a7fc-9825f58075db_1397x670.jpeg 424w, https://substackcdn.com/image/fetch/$s_!DwK8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e9328f7-9410-4d3e-a7fc-9825f58075db_1397x670.jpeg 848w, https://substackcdn.com/image/fetch/$s_!DwK8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e9328f7-9410-4d3e-a7fc-9825f58075db_1397x670.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!DwK8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e9328f7-9410-4d3e-a7fc-9825f58075db_1397x670.jpeg 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 role="img" 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><title></title><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>One great quote that encapsulates this: <em>&#8220;The goal isn&#8217;t to prevent all failures, but to handle them so gracefully that users never notice&#8221;</em>. A perfectly resilient system could be on fire behind the scenes, but from the user&#8217;s perspective, it&#8217;s running smoothly or only minimally affected. Maybe some features are temporarily limited, or a loading spinner takes a second longer, but the overall service remains available.</p><p>In practical terms, this mindset means investing in things like <strong>redundancy</strong> (so one failure doesn&#8217;t take you completely down), <strong>graceful degradation</strong> (if one component is offline, others still provide value), and <strong>automatic recovery</strong> (services restart, self-heal, reroute traffic, etc.). It also means not treating the engineers who caused a failure as villains &#8211; instead, treat each incident as a learning exercise to improve the system (this is more on the human/process side, blameless post-mortems, etc., but it&#8217;s part of the reliability culture).</p><p>To conclude this section, let&#8217;s re-imagine our opening story with a happier ending: You click &#8220;<em>Buy Now</em>&#8221;. The payment service <em>does</em> charge your card but fails to respond. The website&#8217;s client side has a <strong>retry with an idempotency key</strong> in place, so it automatically tries again after a moment. The payment service sees the duplicate request, realizes it&#8217;s the same transaction, and instead of charging twice, it returns &#8220;<em>OK, got it</em>&#8221; along with the receipt from the first charge. The website gets the successful response on the second attempt and shows &#8220;<em>Order confirmed!</em>&#8221; to you. You never even knew there was a hiccup. That&#8217;s a failure that was made uneventful - by design.</p><div><hr></div><p><strong>&#10084;&#65039; If this post helped you understand failure handling in distributed systems, consider sharing it.</strong><br>It helps more people - especially beginners - discover practical explanations without the gatekeeping.</p><p>Sharing the post is one of the best ways you can support my work. Thank you. &#128588;</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/how-systems-handle-failure-retries?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/how-systems-handle-failure-retries?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2>&#9997;&#65039; Summary</h2><p>We covered a lot, so let&#8217;s summarize the key points of how systems handle failure gracefully:</p><ul><li><p><strong>Failures happen constantly in distributed systems</strong> - networks glitch, servers crash, messages duplicate. Reliability comes from <em>managing</em> failures, not magically avoiding them. Design your mindset and system with the expectation of failure.</p></li><li><p><strong>Retries</strong> are the first tool to handle transient issues. By retrying operations that might have failed due to a temporary issue, systems can turn flakiness into success. But retries must be used judiciously: apply <strong>exponential backoff</strong> and <strong>jitter</strong> to avoid thundering herds. Always cap the number of retries. Done right, retries significantly boost availability (e.g., achieving that extra &#8220;<em>nine</em>&#8221; of uptime); done wrong, they cause retry storms that <strong>amplify outages</strong>.</p></li><li><p><strong>Circuit Breakers</strong> act as a safety valve. When a service is consistently failing, the circuit breaker &#8220;<em>opens</em>&#8221; to stop further attempts, preventing overload and giving time to recover. It&#8217;s a protective measure to <strong>fail fast</strong> and avoid cascading failures. With closed, open, half-open states, circuit breakers can gracefully recover and resume operations once the failures subside. Think of it as the system knowing when to say &#8220;<em>enough for now</em>&#8221; for its own good.</p></li><li><p><strong>Idempotency</strong> is the unsung hero that ensures retries (and unexpected repeats) don&#8217;t cause chaos. An idempotent operation yields the same result no matter how many times it&#8217;s performed. By designing APIs and actions to be idempotent (using unique request IDs, deduplication, and careful state management), we make safe retries possible. Idempotency prevents the nightmare of duplicate side effects &#8211; no double charges, no extra emails - even if a message or request is processed twice.</p></li><li><p><strong>Together, these techniques form a self-healing system.</strong> Imagine a scenario: a service hiccups, clients retry (thanks to idempotency, without side effects), a persistent failure triggers a circuit breaker to stop the bleeding, and after a pause the system recovers and continues as normal. Each component (retry, breaker, idempotent design) covers a different aspect, and combined they allow a system to withstand failures large and small without collapsing.</p></li><li><p><strong>Observability</strong> underpins all of this. You need to monitor and measure retries, failures, and recovery actions. Metrics, logs, and traces give you the visibility to tune the system and catch problems early. It&#8217;s how you verify that your retries aren&#8217;t causing harm, or that your circuit breaker isn&#8217;t tripping too often. Observability is your early warning system and debugging aid.</p></li></ul><p>Finally, remember that <strong>resilience is a mindset and a continuous process</strong>. As the saying goes, <em>distributed systems will fail - and that&#8217;s okay</em>. Our job is to build systems that <strong>&#8220;</strong><em><strong>take a deep breath, wait, retry, and carry on</strong></em><strong>&#8221;</strong> when things go wrong. By embracing failure and designing for it, we create software that doesn&#8217;t just avoid crashing, but rather <em>learns to live with failures</em> in a way that users barely notice. That is the art of reliable system design: not preventing rain from ever falling, but carrying an umbrella and wearing waterproof boots so a little rain never stops the parade.</p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p><a href="https://ptgmedia.pearsoncmg.com/images/9780321943187/samplepages/9780321943187.pdf">The Practice of Cloud System Administration</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p><a href="https://dzone.com/articles/overcoming-the-retry-dilemma-in-distributed-systems">Overcoming the Retry Dilemma in Distributed Systems</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p><a href="https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/">Timeouts, retries, and backoff with jitter</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-4" href="#footnote-anchor-4" class="footnote-number" contenteditable="false" target="_self">4</a><div class="footnote-content"><p><a href="https://estuary.dev/blog/exactly-once-delivery/">What is Exactly-Once Delivery and Why It&#8217;s So Hard to Achieve</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-5" href="#footnote-anchor-5" class="footnote-number" contenteditable="false" target="_self">5</a><div class="footnote-content"><p><a href="https://betterstack.com/community/guides/monitoring/exponential-backoff/">Mastering Exponential Backoff in Distributed Systems</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-6" href="#footnote-anchor-6" class="footnote-number" contenteditable="false" target="_self">6</a><div class="footnote-content"><p><a href="https://martinfowler.com/bliki/CircuitBreaker.html">Circuit Breaker</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-7" href="#footnote-anchor-7" class="footnote-number" contenteditable="false" target="_self">7</a><div class="footnote-content"><p><a href="https://learn.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker">Circuit Breaker pattern</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-8" href="#footnote-anchor-8" class="footnote-number" contenteditable="false" target="_self">8</a><div class="footnote-content"><p><a href="https://aws.amazon.com/builders-library/making-retries-safe-with-idempotent-APIs/">Making retries safe with idempotent APIs</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-9" href="#footnote-anchor-9" class="footnote-number" contenteditable="false" target="_self">9</a><div class="footnote-content"><p><a href="https://temporal.io/blog/error-handling-in-distributed-systems"> Error handling in distributed systems: A guide to resilience patterns </a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-10" href="#footnote-anchor-10" class="footnote-number" contenteditable="false" target="_self">10</a><div class="footnote-content"><p><a href="https://microservices.io/post/microservices/patterns/2020/10/16/idempotent-consumer.html">Handling duplicate messages using the Idempotent consumer pattern</a></p></div></div>]]></content:encoded></item><item><title><![CDATA[✨ Scientific ML leads, time-series foundation models generalize, and real-world agent benchmarks temper automation hype]]></title><description><![CDATA[AI Alert]]></description><link>https://iam.slys.dev/p/scientific-ml-leads-time-series-foundation</link><guid isPermaLink="false">https://iam.slys.dev/p/scientific-ml-leads-time-series-foundation</guid><dc:creator><![CDATA[Jakub Slys 🤖]]></dc:creator><pubDate>Wed, 12 Nov 2025 19:20:42 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!CteH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25172b79-f54e-4a87-9fc4-14e3667ffd48_1456x971.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_!CteH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25172b79-f54e-4a87-9fc4-14e3667ffd48_1456x971.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CteH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25172b79-f54e-4a87-9fc4-14e3667ffd48_1456x971.png 424w, https://substackcdn.com/image/fetch/$s_!CteH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25172b79-f54e-4a87-9fc4-14e3667ffd48_1456x971.png 848w, https://substackcdn.com/image/fetch/$s_!CteH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25172b79-f54e-4a87-9fc4-14e3667ffd48_1456x971.png 1272w, https://substackcdn.com/image/fetch/$s_!CteH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25172b79-f54e-4a87-9fc4-14e3667ffd48_1456x971.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CteH!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25172b79-f54e-4a87-9fc4-14e3667ffd48_1456x971.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/25172b79-f54e-4a87-9fc4-14e3667ffd48_1456x971.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:103778,&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://iam.slys.dev/i/178402062?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25172b79-f54e-4a87-9fc4-14e3667ffd48_1456x971.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!CteH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25172b79-f54e-4a87-9fc4-14e3667ffd48_1456x971.png 424w, https://substackcdn.com/image/fetch/$s_!CteH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25172b79-f54e-4a87-9fc4-14e3667ffd48_1456x971.png 848w, https://substackcdn.com/image/fetch/$s_!CteH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25172b79-f54e-4a87-9fc4-14e3667ffd48_1456x971.png 1272w, https://substackcdn.com/image/fetch/$s_!CteH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25172b79-f54e-4a87-9fc4-14e3667ffd48_1456x971.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 role="img" 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><title></title><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>Here s a quick rundown of the key trends in Machine Learning research from the past week.</p><div class="poll-embed" data-attrs="{&quot;id&quot;:402572}" data-component-name="PollToDOM"></div><h1>&#128171; Key Research Trends Last Week</h1><p>By volume, scientific ML applications led (2 papers), alongside promising time-series foundation models and realistic assessments of agentic AI in the wild.</p><ul><li><p>Physics-aware scientific ML is surging, with improved 3D weather nowcasting via gray-box neural operators<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a> and deep-learning 0based simulation-driven cosmology inference at DES Y3 scale<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a>.</p></li><li><p>Time-series foundation models double as strong zero-shot feature extractors for classification, challenging the need for task-specific pretraining<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a>.</p></li><li><p>Real-world agent benchmarks show modest automation on practical remote work tasks, grounding expectations around agent capabilitie<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a>s.</p></li></ul><h1>&#128302; Future Research Directions</h1><p>Expect momentum toward physics-constrained learning, reusable time-series backbones, and reality-checked agent evaluations.</p><ul><li><p>More physically consistent and uncertainty-aware forecasting and multi-probe scientific pipelines will expand to longer horizons and richer modalities.</p></li><li><p>Frozen time-series foundation backbones will see wider reuse across detection, classification, and control tasks with lightweight adaptation.</p></li><li><p>Agent research will pivot toward measurable gains on real workflows and transparency in specialized solvers, guided by rigorous benchmarks and interpretability advances<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a>.</p></li></ul><p>In short: Scientific ML and time-series FMs took center stage while realistic agent evaluations recalibrated expectations.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/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">slys.dev 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><h2>What to watch next week:</h2><ul><li><p>Early demos of physics-guided generative updates for weather/climate and new multi-survey scientific ML pipelines building on DES-style simulation-based inference.</p></li><li><p>Benchmarks or toolkits that package frozen time-series FMs for plug-and-play classification and anomaly detection.</p></li><li><p>Agent evals that measure end-to-end productivity on real tasks (docs, analysis, data wrangling) with transparent failure modes and progress tracking.</p></li></ul><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p><a href="https://arxiv.org/abs/2511.04659v1">Nowcast3D: Reliable precipitation nowcasting via gray-box learning</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p><a href="https://arxiv.org/abs/2511.04681v1">Dark Energy Survey Year 3 results: Simulation-based wCDM inference from weak lensing and galaxy clustering maps with deep learning. I. Analysis design</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p><a href="https://arxiv.org/abs/2510.26777v1">Pre-trained Forecasting Models: Strong Zero-Shot Feature Extractors for Time Series Classification</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-4" href="#footnote-anchor-4" class="footnote-number" contenteditable="false" target="_self">4</a><div class="footnote-content"><p><a href="https://arxiv.org/abs/2510.26787v1">Remote Labor Index: Measuring AI Automation of Remote Work</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-5" href="#footnote-anchor-5" class="footnote-number" contenteditable="false" target="_self">5</a><div class="footnote-content"><p><a href="https://arxiv.org/abs/2510.21693v1">Mechanistic Interpretability for Neural TSP Solvers</a></p><p></p></div></div>]]></content:encoded></item><item><title><![CDATA[How you can automate sharing your Substack to X, Threads, Notes & Bluesky]]></title><description><![CDATA[A journey into protecting your creative spark - by letting a system carry the load]]></description><link>https://iam.slys.dev/p/how-you-can-automate-sharing-your</link><guid isPermaLink="false">https://iam.slys.dev/p/how-you-can-automate-sharing-your</guid><dc:creator><![CDATA[Jakub Slys 🤖]]></dc:creator><pubDate>Thu, 06 Nov 2025 19:20:37 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!hzia!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99f13ae0-a255-4ac4-877f-9c70bdbcb053_1536x1024.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_!hzia!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99f13ae0-a255-4ac4-877f-9c70bdbcb053_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!hzia!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99f13ae0-a255-4ac4-877f-9c70bdbcb053_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!hzia!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99f13ae0-a255-4ac4-877f-9c70bdbcb053_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!hzia!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99f13ae0-a255-4ac4-877f-9c70bdbcb053_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!hzia!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99f13ae0-a255-4ac4-877f-9c70bdbcb053_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!hzia!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99f13ae0-a255-4ac4-877f-9c70bdbcb053_1536x1024.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/99f13ae0-a255-4ac4-877f-9c70bdbcb053_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2197320,&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://iam.slys.dev/i/177886289?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99f13ae0-a255-4ac4-877f-9c70bdbcb053_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!hzia!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99f13ae0-a255-4ac4-877f-9c70bdbcb053_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!hzia!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99f13ae0-a255-4ac4-877f-9c70bdbcb053_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!hzia!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99f13ae0-a255-4ac4-877f-9c70bdbcb053_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!hzia!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99f13ae0-a255-4ac4-877f-9c70bdbcb053_1536x1024.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 role="img" 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><title></title><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>There&#8217;s a unique high to hitting &#8220;<em>Publish</em>&#8221; on a Substack post. Your thoughts, polished and stitched into something coherent, are out in the world. For a few minutes, you&#8217;re proud. Clear-headed. Done.</p><p>It feels like exhaling after holding your breath through edits, drafts, and second-guesses. The post is yours. <strong>Your voice, your tempo, your truth.</strong></p><p>You savor the moment. You refresh once or twice. Maybe someone replies. A handful of hearts. Someone says, &#8220;<em>This hit home</em>&#8221;.</p><p>And then - almost on cue - that quiet pressure creeps in.</p><p>&#8220;<em>Now what?</em>&#8221;</p><p>You open <strong>Threads</strong>. You open <strong>X</strong>. You open <strong>Bluesky</strong>. You open <strong>Substack Notes</strong>. Four tabs. Four different cultures. Four slightly different audiences expecting slightly different versions of the same idea.</p><p>Suddenly, the tone you took 45 minutes to shape gets sliced up by <strong>character limits</strong>. The nuance you threaded into the piece gets crushed by speed-scrolling. You&#8217;re <strong>rewriting</strong> the same intro again - <strong>only punchier</strong>. <strong>Shorter</strong>. <strong>More hashtags?</strong> Fewer? What&#8217;s the vibe on Threads today? Does X still care about links? Is Bluesky better with threads or quotes?</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ii-0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a1ec9d3-6920-4c07-a8b7-980863feb498_1233x1400.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ii-0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a1ec9d3-6920-4c07-a8b7-980863feb498_1233x1400.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Ii-0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a1ec9d3-6920-4c07-a8b7-980863feb498_1233x1400.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Ii-0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a1ec9d3-6920-4c07-a8b7-980863feb498_1233x1400.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Ii-0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a1ec9d3-6920-4c07-a8b7-980863feb498_1233x1400.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ii-0!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a1ec9d3-6920-4c07-a8b7-980863feb498_1233x1400.jpeg" width="1200" height="1362.5304136253042" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2a1ec9d3-6920-4c07-a8b7-980863feb498_1233x1400.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:1400,&quot;width&quot;:1233,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:135917,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/177886289?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a1ec9d3-6920-4c07-a8b7-980863feb498_1233x1400.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Ii-0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a1ec9d3-6920-4c07-a8b7-980863feb498_1233x1400.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Ii-0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a1ec9d3-6920-4c07-a8b7-980863feb498_1233x1400.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Ii-0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a1ec9d3-6920-4c07-a8b7-980863feb498_1233x1400.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Ii-0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a1ec9d3-6920-4c07-a8b7-980863feb498_1233x1400.jpeg 1456w" sizes="100vw"></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 role="img" 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><title></title><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>The tools don&#8217;t help. They&#8217;re not built for writers - they&#8217;re built for velocity. You&#8217;re backspacing more than you&#8217;re creating. <strong>Your energy is not going toward expression, but toward translation. Between formats. Between tones. Between apps.</strong></p><p>Your browser is now a distribution factory. A cold one. <strong>It&#8217;s all CTRL+C and CTRL+V</strong>. Your own words feel like a burden.</p><p><strong>What&#8217;s worse? You start to dread publishing.</strong></p><p>You dread the half hour after the high.</p><p>Because you know what&#8217;s coming.</p><blockquote><p><em>&#8220;I was spending more time distributing my words than writing them.&#8221;</em></p></blockquote><p>And that&#8217;s when the real question began echoing louder and louder:</p><div class="pullquote"><p><strong>&#8220;What if I could keep the creative parts &#8212; and let a system handle the rest?&#8221;</strong></p></div><blockquote><p>&#128161; <strong>Just want the workflows?</strong></p><p>If you&#8217;re here for the ready-to-use n8n automations, feel free to scroll down straight to the &#128206; download section.</p></blockquote><div><hr></div><h1>&#128161; <em>Why I decided to automate (and how AI became my co-writer)</em></h1><p>It started with curiosity. Just a passing thought during one of those post-distribution slogs: Could I build a system that took care of all this - without losing what made my writing feel like me?</p><p>But it wasn&#8217;t really curiosity. It was fatigue. Emotional, cognitive fatigue - the kind that builds up silently. Like condensation on a window, until one day it finally blurs your view.</p><p>I remember staring at five open tabs. Threads. Bluesky. X. Substack Notes. A spreadsheet with ideas half-formed, half-forgotten. I wasn&#8217;t editing anymore - I was copy-pasting. Not creating - just parsing. And with every repackaged line, something in me dimmed. The joy of writing hadn&#8217;t gone anywhere. But everything around it - the busywork, the formatting, the endless tweaking - made me dread the part I used to love most: sharing.</p><p>The real decision came in a moment of strange clarity. I realized I was resenting my own creativity. I&#8217;d pour myself into a Substack post, feel proud of it - and then immediately wish I hadn&#8217;t written it. Because I knew what followed. The relay race. The slicing. The &#8220;<em>which version fits where</em>&#8221; routine. It wasn&#8217;t sustainable. Not if I wanted to keep showing up honestly.</p><p>That&#8217;s when I started poking around with automation again. First, out of a sense of survival. But quickly, it became something else: play.</p><p>The more I tinkered with AI, the more it surprised me. It wasn&#8217;t just capable of summarizing - it could adapt. It could sound like me. I&#8217;d feed it a long-form post, and out would come three punchy Threads, a heartfelt Bluesky post, or a Substack Note that actually carried nuance. And it didn&#8217;t feel like a compromise.</p><p>It felt like... collaboration.</p><p>AI didn&#8217;t act like a ghostwriter. It acted like a lens. It helped reshape my ideas for other contexts - without flattening them. More than anything, it didn&#8217;t complain. It didn&#8217;t get tired. It didn&#8217;t mind formatting the same sentence five different ways or checking whether a hashtag still made sense. It made the exhausting parts... invisible.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!aCqh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33fff400-d09d-401a-bb27-8114ea72aa5d_1415x636.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!aCqh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33fff400-d09d-401a-bb27-8114ea72aa5d_1415x636.jpeg 424w, https://substackcdn.com/image/fetch/$s_!aCqh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33fff400-d09d-401a-bb27-8114ea72aa5d_1415x636.jpeg 848w, https://substackcdn.com/image/fetch/$s_!aCqh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33fff400-d09d-401a-bb27-8114ea72aa5d_1415x636.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!aCqh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33fff400-d09d-401a-bb27-8114ea72aa5d_1415x636.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!aCqh!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33fff400-d09d-401a-bb27-8114ea72aa5d_1415x636.jpeg" width="1200" height="539.3639575971731" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/33fff400-d09d-401a-bb27-8114ea72aa5d_1415x636.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:636,&quot;width&quot;:1415,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:80168,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/177886289?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33fff400-d09d-401a-bb27-8114ea72aa5d_1415x636.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!aCqh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33fff400-d09d-401a-bb27-8114ea72aa5d_1415x636.jpeg 424w, https://substackcdn.com/image/fetch/$s_!aCqh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33fff400-d09d-401a-bb27-8114ea72aa5d_1415x636.jpeg 848w, https://substackcdn.com/image/fetch/$s_!aCqh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33fff400-d09d-401a-bb27-8114ea72aa5d_1415x636.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!aCqh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F33fff400-d09d-401a-bb27-8114ea72aa5d_1415x636.jpeg 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 role="img" 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><title></title><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>This wasn&#8217;t about taking myself out of the process. It was about putting my full self back into the part that mattered. Writing with presence. Publishing with peace.</p><div class="pullquote"><p><strong>&#8220;If I could automate the repeatable, I could reclaim the irreplaceable &#8212; focus, depth, and time to think.&#8221;</strong></p></div><p>And n8n was the right canvas for the job. I didn&#8217;t need a SaaS tool with opinions. I needed building blocks. Something visual, something flexible, something open. n8n could talk to Substack, pass drafts to OpenAI, update Telegram, post to Threads - and just keep flowing.</p><p>So I grabbed my notebook. Scribbled out a map. Then opened n8n and dragged in the first node. A trigger here. A prompt there. I started weaving logic into narrative. It felt like writing - but with a different kind of language.</p><p>I was no longer just writing posts. I was designing the system that would carry them. And for the first time in a long while, I felt like I was protecting my craft - not sacrificing it.</p><h1>&#9881;&#65039; <em>How I designed my automation stack</em></h1><p>Let me take you behind the curtain. Because behind every &#8220;<em>effortless</em>&#8221; flow is a system that was built with care.</p><p>My stack? <strong>Surprisingly lean. Modular. And, dare I say, elegant.</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!eUlT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a2c900a-e8ff-41e5-adeb-2fccd2e4939f_1431x865.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eUlT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a2c900a-e8ff-41e5-adeb-2fccd2e4939f_1431x865.jpeg 424w, https://substackcdn.com/image/fetch/$s_!eUlT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a2c900a-e8ff-41e5-adeb-2fccd2e4939f_1431x865.jpeg 848w, https://substackcdn.com/image/fetch/$s_!eUlT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a2c900a-e8ff-41e5-adeb-2fccd2e4939f_1431x865.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!eUlT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a2c900a-e8ff-41e5-adeb-2fccd2e4939f_1431x865.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!eUlT!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a2c900a-e8ff-41e5-adeb-2fccd2e4939f_1431x865.jpeg" width="1200" height="725.3668763102726" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7a2c900a-e8ff-41e5-adeb-2fccd2e4939f_1431x865.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:865,&quot;width&quot;:1431,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:87471,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/177886289?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a2c900a-e8ff-41e5-adeb-2fccd2e4939f_1431x865.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!eUlT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a2c900a-e8ff-41e5-adeb-2fccd2e4939f_1431x865.jpeg 424w, https://substackcdn.com/image/fetch/$s_!eUlT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a2c900a-e8ff-41e5-adeb-2fccd2e4939f_1431x865.jpeg 848w, https://substackcdn.com/image/fetch/$s_!eUlT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a2c900a-e8ff-41e5-adeb-2fccd2e4939f_1431x865.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!eUlT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a2c900a-e8ff-41e5-adeb-2fccd2e4939f_1431x865.jpeg 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 role="img" 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><title></title><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>At the center was <strong>n8n</strong> - my automation canvas. Visual, node-based, and open-source. I could see the flow of data as it moved. I could shape logic like sentences. I could debug with my eyes. It made me feel like a systems thinker, not just a writer with an idea.</p><p>Feeding it all was the <strong>Substack API</strong>. That was my source of truth. My original content, the long-form stuff, lived there.</p><p>Then came the <strong>OpenAI API</strong>. My collaborator. I didn&#8217;t treat it like a shortcut. I treated it like a filter for nuance. I wrote prompts the way I write intros: carefully. I gave context. I explained tone. And in return, it helped me distill my posts into formats fit for Threads, X, Bluesky, and Notes - without losing the soul.</p><p>To glue it together, I added <strong>Telegram</strong>. A simple reminder system. Whenever new notes were created, I&#8217;d get a ping. &#8220;<em>Your Majesty, I&#8217;ve created Notes from [Post Title]. Remember to approve them!</em>&#8221; Cheeky, sure. But it made the system feel alive. Responsive. Collaborative.</p><p>And then, the unsung hero: <strong>n8n Data Tables</strong>. My mini CMS. No need for Airtable or Notion. Just structured tables that stored everything: full posts, mini-notes, publishing status, access tokens. All right inside n8n.</p><p>But to really make this dance, I needed a few community-built tools. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!TtVr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5872de0a-fc6d-44d1-82d8-cbba3aeb0a22_1473x797.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!TtVr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5872de0a-fc6d-44d1-82d8-cbba3aeb0a22_1473x797.jpeg 424w, https://substackcdn.com/image/fetch/$s_!TtVr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5872de0a-fc6d-44d1-82d8-cbba3aeb0a22_1473x797.jpeg 848w, https://substackcdn.com/image/fetch/$s_!TtVr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5872de0a-fc6d-44d1-82d8-cbba3aeb0a22_1473x797.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!TtVr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5872de0a-fc6d-44d1-82d8-cbba3aeb0a22_1473x797.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!TtVr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5872de0a-fc6d-44d1-82d8-cbba3aeb0a22_1473x797.jpeg" width="1456" height="788" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5872de0a-fc6d-44d1-82d8-cbba3aeb0a22_1473x797.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:788,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:87374,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/177886289?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5872de0a-fc6d-44d1-82d8-cbba3aeb0a22_1473x797.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!TtVr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5872de0a-fc6d-44d1-82d8-cbba3aeb0a22_1473x797.jpeg 424w, https://substackcdn.com/image/fetch/$s_!TtVr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5872de0a-fc6d-44d1-82d8-cbba3aeb0a22_1473x797.jpeg 848w, https://substackcdn.com/image/fetch/$s_!TtVr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5872de0a-fc6d-44d1-82d8-cbba3aeb0a22_1473x797.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!TtVr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5872de0a-fc6d-44d1-82d8-cbba3aeb0a22_1473x797.jpeg 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 role="img" 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><title></title><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>That&#8217;s the beauty of n8n - it grows with its people. So I added:</p><ul><li><p><code>n8n-nodes-substack</code> - to pull content directly from Substack.</p></li><li><p><code>n8n-nodes-bluesky-enhanced</code> - to post to Bluesky with proper threading.</p></li><li><p><code>n8n-nodes-oauth2-token</code> - to automate token refresh flows for Meta Threads.</p></li></ul><p>These weren&#8217;t just add-ons. They were upgrades. Extensions of capability, created by other builders solving their own creative problems.</p><p>Once all the pieces were in place, I sketched out my manual workflow on paper:</p><ol><li><p>Check for new post</p></li><li><p>Generate short-form content</p></li><li><p>Approve and publish</p></li><li><p>Refresh tokens</p></li></ol><p>Then, I recreated it inside n8n. Node by node. Condition by condition. The end result?</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!QdBO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f75c8f4-1164-435c-8915-176c9830657a_1373x1345.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QdBO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f75c8f4-1164-435c-8915-176c9830657a_1373x1345.jpeg 424w, https://substackcdn.com/image/fetch/$s_!QdBO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f75c8f4-1164-435c-8915-176c9830657a_1373x1345.jpeg 848w, https://substackcdn.com/image/fetch/$s_!QdBO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f75c8f4-1164-435c-8915-176c9830657a_1373x1345.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!QdBO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f75c8f4-1164-435c-8915-176c9830657a_1373x1345.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QdBO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f75c8f4-1164-435c-8915-176c9830657a_1373x1345.jpeg" width="1373" height="1345" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8f75c8f4-1164-435c-8915-176c9830657a_1373x1345.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1345,&quot;width&quot;:1373,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:132037,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/177886289?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f75c8f4-1164-435c-8915-176c9830657a_1373x1345.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!QdBO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f75c8f4-1164-435c-8915-176c9830657a_1373x1345.jpeg 424w, https://substackcdn.com/image/fetch/$s_!QdBO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f75c8f4-1164-435c-8915-176c9830657a_1373x1345.jpeg 848w, https://substackcdn.com/image/fetch/$s_!QdBO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f75c8f4-1164-435c-8915-176c9830657a_1373x1345.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!QdBO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f75c8f4-1164-435c-8915-176c9830657a_1373x1345.jpeg 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 role="img" 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><title></title><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><ul><li><p><strong>Substack Scraper</strong> - checks for new posts daily</p></li><li><p><strong>Notes Factory</strong> - turns those into platform-ready snippets via GPT-4</p></li><li><p><strong>Publishing Engine</strong> - posts only the approved content to Threads, X, Bluesky, and more</p></li><li><p><strong>Token Refresh</strong> - keeps my credentials alive, quietly</p></li></ul><p>The whole thing runs on autopilot. It costs me cents per week. And for every post I write, it generates a cascade of thoughtful, tailored updates for multiple channels.</p><div class="pullquote"><p><strong>&#8220;One post goes in, sixty platform-ready updates come out &#8212; all in my voice.&#8221;</strong></p></div><h1>&#129521; <em>The n8n Data Tables (my miniature content CMS)</em></h1><p>n8n&#8217;s <strong>Data Tables<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></strong> were a revelation.</p><p>Before them, I was juggling Google Sheets, Notion pages, and duct-taped databases. None of them were native to n8n. None of them felt built for the kind of structured, iterative automation I was dreaming of. I wanted something fast, internal, and purpose-built. Something that didn&#8217;t break just because a column name changed.</p><p>Data Tables arrived like a breath of fresh air. No more context switching. No more third-party sync issues. Just structured, queryable storage, built directly into the same platform running my automations. It felt like having a lightweight CMS stitched into the bones of my workflow.</p><p>I designed my tables like a writer would design a workspace - with intention, clarity, and flow:</p><ul><li><p><code>My Substack Posts</code> - the archive of everything I&#8217;ve published. Each row represents a post, with columns like:</p><ul><li><p><code>post_id (number)</code>: uniquely identifies the Substack post</p></li><li><p><code>post_date (datetime)</code>: the date of the post publishing</p></li><li><p><code>post_title (string)</code>: the original headline</p></li><li><p><code>post_link (string)</code>: direct link for reference or inclusion</p></li><li><p><code>description (string)</code>: a short preview or blurb</p></li><li><p><code>content (string)</code>: full markdown body for AI processing</p></li><li><p><code>exhausted (boolean)</code>: whether it&#8217;s already used for Notes</p></li></ul></li><li><p><code>Notes from Posts</code> - the creative goldmine. This is where AI-generated snippets live. Each row is a mini-post or thought derived from a longform Substack piece. Columns include:</p><ul><li><p><code>note_id (string)</code>: uniquely identifies created note</p></li><li><p><code>post_id (number)</code>: uniquely identifies the Substack post</p></li><li><p><code>post_url (string)</code>: direct post link</p></li><li><p><code>post_date (datetime)</code>: the date of the post publishing</p></li><li><p><code>note_platform (string)</code>: which channel the note is designed for (X, Threads, Bluesky, Notes)</p></li><li><p><code>content (string)</code>: the actual note content</p></li><li><p><code>hashtags (string)</code>: optional, platform-specific tags</p></li><li><p><code>approved (boolean)</code>: whether it&#8217;s approved</p></li><li><p><code>exhausted (boolean)</code>: whether it&#8217;s already published</p></li></ul></li><li><p><code>Tokens</code> - silent but essential. This table holds OAuth tokens for APIs that require them, especially Threads. Columns like:</p><ul><li><p><code>name (string)</code>: name of the token</p></li><li><p><code>value (string)</code>: it&#8217;s value</p></li></ul></li></ul><p>Every table has a clear job. Nothing overlaps. It&#8217;s calm. Predictable. Writable by bots. Reviewable by humans.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!94c3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc8bfbec-898f-4d3d-8ee4-e2a0449ef40e_1551x738.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!94c3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc8bfbec-898f-4d3d-8ee4-e2a0449ef40e_1551x738.jpeg 424w, https://substackcdn.com/image/fetch/$s_!94c3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc8bfbec-898f-4d3d-8ee4-e2a0449ef40e_1551x738.jpeg 848w, https://substackcdn.com/image/fetch/$s_!94c3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc8bfbec-898f-4d3d-8ee4-e2a0449ef40e_1551x738.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!94c3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc8bfbec-898f-4d3d-8ee4-e2a0449ef40e_1551x738.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!94c3!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc8bfbec-898f-4d3d-8ee4-e2a0449ef40e_1551x738.jpeg" width="1200" height="571.1538461538462" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cc8bfbec-898f-4d3d-8ee4-e2a0449ef40e_1551x738.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:693,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:199281,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/177886289?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc8bfbec-898f-4d3d-8ee4-e2a0449ef40e_1551x738.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!94c3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc8bfbec-898f-4d3d-8ee4-e2a0449ef40e_1551x738.jpeg 424w, https://substackcdn.com/image/fetch/$s_!94c3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc8bfbec-898f-4d3d-8ee4-e2a0449ef40e_1551x738.jpeg 848w, https://substackcdn.com/image/fetch/$s_!94c3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc8bfbec-898f-4d3d-8ee4-e2a0449ef40e_1551x738.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!94c3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc8bfbec-898f-4d3d-8ee4-e2a0449ef40e_1551x738.jpeg 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 role="img" 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><title></title><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="pullquote"><p><strong>&#8220;Data Tables didn&#8217;t just store my content. They made the whole system feel... writable.&#8221;</strong></p></div><p>They became the internal language of my automation. And just like paragraphs build a story - rows build a system.</p><h1>&#129302; <em>How automation quietly creates art while you sleep</em></h1><p>Every morning, my system breathes into action like a well-trained assistant who knows my rhythms better than I do.</p><p>It begins with n8n&#8217;s silent scan - a check-in with Substack. Like a librarian reviewing the shelves, it looks for anything new I&#8217;ve published. If it finds something, it pulls it in gently and feeds it into GPT-4, my creative apprentice.</p><p>This is where the real magic unfolds: the Notes Factory stirs to life. GPT-4 reads the post with more patience than I ever could. It identifies key ideas, distills tone, and transforms my long-form reflections into platform-native gems. Not watered-down versions - reframed perspectives. Some fit the punchiness of X. Others settle into the warmth of Threads. Bluesky gets thoughtful riffs. Substack Notes receives the stripped-down essence.</p><p>These pieces - short, sharp, and true to my tone - are deposited into the <code>Notes from Posts</code> Data Table. Each entry knows what it is and where it&#8217;s going. The table holds:</p><ul><li><p>The note&#8217;s text</p></li><li><p>Its target platform</p></li><li><p>Related hashtags</p></li><li><p>Its status (approved, published)</p></li><li><p>The post it came from</p></li></ul><p>And then - my favorite part - a notification. Telegram whispers:</p><blockquote><p><em>&#8220;Your Majesty, I&#8217;ve created Notes from [Post Title]. Remember to approve them!&#8221;</em></p></blockquote><p>It always makes me smile. This isn&#8217;t a cold automation. It&#8217;s a collaboration that respects my creative mood.</p><p>I open the table and begin reviewing. Sometimes I change a word. Sometimes I let the note stand. But I&#8217;m never starting from scratch. I&#8217;m editing - not reinventing. The difference is everything.</p><p>When I flip the status to &#8220;<em>approved</em>&#8221;, the Publishing Engine takes over like a trusted courier. It moves quietly, posting each note where it belongs. Threads. X. Bluesky. Notes. One by one, right on time.</p><p>There are no alerts. No extra clicks. No tabs to juggle.</p><div class="pullquote"><p><strong>&#8220;Automation doesn&#8217;t replace your voice. It clears the noise around it.&#8221;</strong></p></div><p>And by the time I sip my coffee, my words are already making their way into the world.</p><h1>&#129504; <em>What I learned about creativity, AI, and letting go</em></h1><p>This system didn&#8217;t just save time. It gave me back a piece of myself.</p><p>At first, I thought I was building a productivity tool. But what emerged was something softer - a system that knew how to get out of the way. It didn&#8217;t push me to do more. It simply removed the guilt of doing less.</p><p>No more mental tax from wondering if I&#8217;d reshared a post. No more half-hearted edits to fit platforms I barely had time to engage with. And most importantly, no more creative whiplash - that jarring shift from writing in flow to hacking my own words apart just to make them &#8220;<em>fit</em>&#8221;.</p><p>Instead, I write with a kind of inner permission. I know my voice won&#8217;t be diluted by distribution. It will be amplified.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2WU1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6368cd82-da57-489a-bdef-3a704ffb1c28_940x1600.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2WU1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6368cd82-da57-489a-bdef-3a704ffb1c28_940x1600.jpeg 424w, https://substackcdn.com/image/fetch/$s_!2WU1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6368cd82-da57-489a-bdef-3a704ffb1c28_940x1600.jpeg 848w, https://substackcdn.com/image/fetch/$s_!2WU1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6368cd82-da57-489a-bdef-3a704ffb1c28_940x1600.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!2WU1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6368cd82-da57-489a-bdef-3a704ffb1c28_940x1600.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2WU1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6368cd82-da57-489a-bdef-3a704ffb1c28_940x1600.jpeg" width="940" height="1600" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6368cd82-da57-489a-bdef-3a704ffb1c28_940x1600.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1600,&quot;width&quot;:940,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:121490,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/177886289?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6368cd82-da57-489a-bdef-3a704ffb1c28_940x1600.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!2WU1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6368cd82-da57-489a-bdef-3a704ffb1c28_940x1600.jpeg 424w, https://substackcdn.com/image/fetch/$s_!2WU1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6368cd82-da57-489a-bdef-3a704ffb1c28_940x1600.jpeg 848w, https://substackcdn.com/image/fetch/$s_!2WU1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6368cd82-da57-489a-bdef-3a704ffb1c28_940x1600.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!2WU1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6368cd82-da57-489a-bdef-3a704ffb1c28_940x1600.jpeg 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 role="img" 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><title></title><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>The AI never overwrites my tone. It simply echoes it in smaller frames. Reframes it. Makes it travel.</p><p>And in the stillness of this new rhythm, I found something I hadn&#8217;t expected: <strong>peace</strong>. Not just with my process, but with myself.</p><div class="pullquote"><p><strong>&#8220;I didn&#8217;t delegate my creativity. I protected it.&#8221;</strong></p></div><p>Now I publish more consistently - not just on Substack, but everywhere. And it doesn&#8217;t feel like obligation. It feels like expression finally given the room it deserves.</p><p>The system isn&#8217;t a shortcut. It&#8217;s scaffolding. Built not to replace the artist - but to hold the weight of repetition, so the artist can stay free.</p><div><hr></div><p>&#128172; <strong>I&#8217;d love to hear from you!</strong></p><p>Have questions about specific nodes? Got your own spin on this workflow? Or just want to say it sparked something? Leave a comment - I read every one and reply when I can.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/how-you-can-automate-sharing-your/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/how-you-can-automate-sharing-your/comments"><span>Leave a comment</span></a></p><div><hr></div><h1>&#129668; How you can build yours &#8212; <em>a beginner-friendly blueprint</em></h1><p>You don&#8217;t need to be an engineer. Just curious enough to wire blocks together - and to dream about what it would feel like if distribution didn&#8217;t drain you anymore.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YWBZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b734e92-03ad-476e-9271-dc42996a9577_1373x928.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YWBZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b734e92-03ad-476e-9271-dc42996a9577_1373x928.jpeg 424w, https://substackcdn.com/image/fetch/$s_!YWBZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b734e92-03ad-476e-9271-dc42996a9577_1373x928.jpeg 848w, https://substackcdn.com/image/fetch/$s_!YWBZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b734e92-03ad-476e-9271-dc42996a9577_1373x928.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!YWBZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b734e92-03ad-476e-9271-dc42996a9577_1373x928.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YWBZ!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b734e92-03ad-476e-9271-dc42996a9577_1373x928.jpeg" width="1200" height="811.0706482155863" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4b734e92-03ad-476e-9271-dc42996a9577_1373x928.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:928,&quot;width&quot;:1373,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:118779,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/177886289?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b734e92-03ad-476e-9271-dc42996a9577_1373x928.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!YWBZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b734e92-03ad-476e-9271-dc42996a9577_1373x928.jpeg 424w, https://substackcdn.com/image/fetch/$s_!YWBZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b734e92-03ad-476e-9271-dc42996a9577_1373x928.jpeg 848w, https://substackcdn.com/image/fetch/$s_!YWBZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b734e92-03ad-476e-9271-dc42996a9577_1373x928.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!YWBZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b734e92-03ad-476e-9271-dc42996a9577_1373x928.jpeg 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 role="img" 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><title></title><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>Let&#8217;s walk through the exact blueprint I built - piece by piece.</p><h2>1&#65039;&#8419; Substack Scraper</h2><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!rRQb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F317c9904-9c0b-4135-b396-7d140dde7e42_1485x342.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rRQb!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F317c9904-9c0b-4135-b396-7d140dde7e42_1485x342.png 424w, https://substackcdn.com/image/fetch/$s_!rRQb!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F317c9904-9c0b-4135-b396-7d140dde7e42_1485x342.png 848w, https://substackcdn.com/image/fetch/$s_!rRQb!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F317c9904-9c0b-4135-b396-7d140dde7e42_1485x342.png 1272w, https://substackcdn.com/image/fetch/$s_!rRQb!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F317c9904-9c0b-4135-b396-7d140dde7e42_1485x342.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!rRQb!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F317c9904-9c0b-4135-b396-7d140dde7e42_1485x342.png" width="1200" height="276.3636363636364" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/317c9904-9c0b-4135-b396-7d140dde7e42_1485x342.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:342,&quot;width&quot;:1485,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:73765,&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://iam.slys.dev/i/177886289?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f3b9493-b153-49c3-b9b7-bcc0b052f574_1653x913.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!rRQb!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F317c9904-9c0b-4135-b396-7d140dde7e42_1485x342.png 424w, https://substackcdn.com/image/fetch/$s_!rRQb!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F317c9904-9c0b-4135-b396-7d140dde7e42_1485x342.png 848w, https://substackcdn.com/image/fetch/$s_!rRQb!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F317c9904-9c0b-4135-b396-7d140dde7e42_1485x342.png 1272w, https://substackcdn.com/image/fetch/$s_!rRQb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F317c9904-9c0b-4135-b396-7d140dde7e42_1485x342.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p><strong>&#9200; Schedule Trigger</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ow9b!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40e0f93b-1612-491b-b9db-6693dde59a33_623x549.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ow9b!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40e0f93b-1612-491b-b9db-6693dde59a33_623x549.png 424w, https://substackcdn.com/image/fetch/$s_!Ow9b!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40e0f93b-1612-491b-b9db-6693dde59a33_623x549.png 848w, https://substackcdn.com/image/fetch/$s_!Ow9b!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40e0f93b-1612-491b-b9db-6693dde59a33_623x549.png 1272w, https://substackcdn.com/image/fetch/$s_!Ow9b!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40e0f93b-1612-491b-b9db-6693dde59a33_623x549.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ow9b!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40e0f93b-1612-491b-b9db-6693dde59a33_623x549.png" width="623" height="549" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/40e0f93b-1612-491b-b9db-6693dde59a33_623x549.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:549,&quot;width&quot;:623,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:43616,&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://iam.slys.dev/i/177886289?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6a1a8f6-fde2-4367-976f-fa4334d094e7_639x922.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_!Ow9b!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40e0f93b-1612-491b-b9db-6693dde59a33_623x549.png 424w, https://substackcdn.com/image/fetch/$s_!Ow9b!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40e0f93b-1612-491b-b9db-6693dde59a33_623x549.png 848w, https://substackcdn.com/image/fetch/$s_!Ow9b!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40e0f93b-1612-491b-b9db-6693dde59a33_623x549.png 1272w, https://substackcdn.com/image/fetch/$s_!Ow9b!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40e0f93b-1612-491b-b9db-6693dde59a33_623x549.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 role="img" 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><title></title><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>This is where the journey begins - the bridge between the words I&#8217;ve poured into Substack and the engine that carries them forward. The workflow kicks off with the <strong>Schedule Trigger</strong> node, configured to run daily at 8am. It&#8217;s a deliberate choice - the same hour I often open my laptop with coffee and curiosity. The node needs almost nothing: just a recurrence rule set to daily. That&#8217;s it. It&#8217;s the morning bell that wakes up the rest of the system.</p><p><strong>&#128240; Substack Node</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!PStZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9aef082-55c3-4ff1-8f62-6cc71cb8dc7c_524x352.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!PStZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9aef082-55c3-4ff1-8f62-6cc71cb8dc7c_524x352.png 424w, https://substackcdn.com/image/fetch/$s_!PStZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9aef082-55c3-4ff1-8f62-6cc71cb8dc7c_524x352.png 848w, https://substackcdn.com/image/fetch/$s_!PStZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9aef082-55c3-4ff1-8f62-6cc71cb8dc7c_524x352.png 1272w, https://substackcdn.com/image/fetch/$s_!PStZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9aef082-55c3-4ff1-8f62-6cc71cb8dc7c_524x352.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!PStZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9aef082-55c3-4ff1-8f62-6cc71cb8dc7c_524x352.png" width="524" height="352" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d9aef082-55c3-4ff1-8f62-6cc71cb8dc7c_524x352.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:352,&quot;width&quot;:524,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:24547,&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://iam.slys.dev/i/177886289?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdff26cf6-3c4a-4e05-81a1-108ce99ec6fd_541x913.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_!PStZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9aef082-55c3-4ff1-8f62-6cc71cb8dc7c_524x352.png 424w, https://substackcdn.com/image/fetch/$s_!PStZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9aef082-55c3-4ff1-8f62-6cc71cb8dc7c_524x352.png 848w, https://substackcdn.com/image/fetch/$s_!PStZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9aef082-55c3-4ff1-8f62-6cc71cb8dc7c_524x352.png 1272w, https://substackcdn.com/image/fetch/$s_!PStZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9aef082-55c3-4ff1-8f62-6cc71cb8dc7c_524x352.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 role="img" 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><title></title><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>Next in line is the <strong>Substack Node</strong>, powered by the community-built <code>n8n-nodes-substack</code>. It fetches my latest posts using the <em>post</em> resource, with a limit of 999 - a generous catch-all that ensures nothing slips through. The credentials use my Substack API key, stored securely. The node returns a clean package of metadata: ID, title, short description, publish date, and URL - the DNA of every article.</p><p><strong>&#128203; Data Table &#8212; My Substack Posts</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NhgO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82eb5a4d-ee65-4e18-9ad6-c616e858de54_524x512.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NhgO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82eb5a4d-ee65-4e18-9ad6-c616e858de54_524x512.png 424w, https://substackcdn.com/image/fetch/$s_!NhgO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82eb5a4d-ee65-4e18-9ad6-c616e858de54_524x512.png 848w, https://substackcdn.com/image/fetch/$s_!NhgO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82eb5a4d-ee65-4e18-9ad6-c616e858de54_524x512.png 1272w, https://substackcdn.com/image/fetch/$s_!NhgO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82eb5a4d-ee65-4e18-9ad6-c616e858de54_524x512.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NhgO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82eb5a4d-ee65-4e18-9ad6-c616e858de54_524x512.png" width="524" height="512" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/82eb5a4d-ee65-4e18-9ad6-c616e858de54_524x512.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:512,&quot;width&quot;:524,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:33216,&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://iam.slys.dev/i/177886289?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca1ca484-647f-4fcf-a27c-57aaef8c29b5_543x909.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_!NhgO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82eb5a4d-ee65-4e18-9ad6-c616e858de54_524x512.png 424w, https://substackcdn.com/image/fetch/$s_!NhgO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82eb5a4d-ee65-4e18-9ad6-c616e858de54_524x512.png 848w, https://substackcdn.com/image/fetch/$s_!NhgO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82eb5a4d-ee65-4e18-9ad6-c616e858de54_524x512.png 1272w, https://substackcdn.com/image/fetch/$s_!NhgO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82eb5a4d-ee65-4e18-9ad6-c616e858de54_524x512.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 role="img" 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><title></title><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>Now the system asks: <em>Are these posts already in my library?</em> To answer, the <strong>Data Table Node</strong> points to <code>My Substack Posts</code>. It pulls the full table - every post that&#8217;s been seen before.</p><p><strong>&#129309; Merge Node</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Axgh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d9e40b7-9f78-45f5-bfbe-b72894c9f911_522x802.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Axgh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d9e40b7-9f78-45f5-bfbe-b72894c9f911_522x802.png 424w, https://substackcdn.com/image/fetch/$s_!Axgh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d9e40b7-9f78-45f5-bfbe-b72894c9f911_522x802.png 848w, https://substackcdn.com/image/fetch/$s_!Axgh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d9e40b7-9f78-45f5-bfbe-b72894c9f911_522x802.png 1272w, https://substackcdn.com/image/fetch/$s_!Axgh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d9e40b7-9f78-45f5-bfbe-b72894c9f911_522x802.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Axgh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d9e40b7-9f78-45f5-bfbe-b72894c9f911_522x802.png" width="522" height="802" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5d9e40b7-9f78-45f5-bfbe-b72894c9f911_522x802.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:802,&quot;width&quot;:522,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:53259,&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://iam.slys.dev/i/177886289?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F821c743e-4691-4a94-b759-13c1fc65e774_547x912.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_!Axgh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d9e40b7-9f78-45f5-bfbe-b72894c9f911_522x802.png 424w, https://substackcdn.com/image/fetch/$s_!Axgh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d9e40b7-9f78-45f5-bfbe-b72894c9f911_522x802.png 848w, https://substackcdn.com/image/fetch/$s_!Axgh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d9e40b7-9f78-45f5-bfbe-b72894c9f911_522x802.png 1272w, https://substackcdn.com/image/fetch/$s_!Axgh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d9e40b7-9f78-45f5-bfbe-b72894c9f911_522x802.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 role="img" 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><title></title><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>Then comes the <strong>Merge Node</strong>, running in advanced mode. It compares <code>post_id</code> from my stored database with <code>id</code> from the fetched previews. If there&#8217;s a mismatch - it means we&#8217;ve found a new story. Those posts continue on their journey while the rest quietly exit the flow.</p><p><strong>&#129534; Full Fetch via Substack Node</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!r2_v!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30dd9b04-42c5-4163-9521-b231ee543a8a_521x356.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!r2_v!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30dd9b04-42c5-4163-9521-b231ee543a8a_521x356.png 424w, https://substackcdn.com/image/fetch/$s_!r2_v!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30dd9b04-42c5-4163-9521-b231ee543a8a_521x356.png 848w, https://substackcdn.com/image/fetch/$s_!r2_v!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30dd9b04-42c5-4163-9521-b231ee543a8a_521x356.png 1272w, https://substackcdn.com/image/fetch/$s_!r2_v!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30dd9b04-42c5-4163-9521-b231ee543a8a_521x356.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!r2_v!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30dd9b04-42c5-4163-9521-b231ee543a8a_521x356.png" width="521" height="356" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/30dd9b04-42c5-4163-9521-b231ee543a8a_521x356.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:356,&quot;width&quot;:521,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:26659,&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://iam.slys.dev/i/177886289?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88335d5f-fc24-4596-b871-012055e4da09_547x912.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_!r2_v!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30dd9b04-42c5-4163-9521-b231ee543a8a_521x356.png 424w, https://substackcdn.com/image/fetch/$s_!r2_v!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30dd9b04-42c5-4163-9521-b231ee543a8a_521x356.png 848w, https://substackcdn.com/image/fetch/$s_!r2_v!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30dd9b04-42c5-4163-9521-b231ee543a8a_521x356.png 1272w, https://substackcdn.com/image/fetch/$s_!r2_v!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30dd9b04-42c5-4163-9521-b231ee543a8a_521x356.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 role="img" 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><title></title><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>For each newcomer, a second <strong>Substack Node</strong> springs to life - this time calling the <code>getPostById</code> operation. It retrieves the complete markdown. This step is crucial: GPT-4 and automation alike need full context to create something meaningful, not fragments.</p><p><strong>&#128190; Upsert to Data Table</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!rTL0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feff7df66-8e36-4b2b-a79e-d772ccf88a9c_521x882.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rTL0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feff7df66-8e36-4b2b-a79e-d772ccf88a9c_521x882.png 424w, https://substackcdn.com/image/fetch/$s_!rTL0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feff7df66-8e36-4b2b-a79e-d772ccf88a9c_521x882.png 848w, https://substackcdn.com/image/fetch/$s_!rTL0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feff7df66-8e36-4b2b-a79e-d772ccf88a9c_521x882.png 1272w, https://substackcdn.com/image/fetch/$s_!rTL0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feff7df66-8e36-4b2b-a79e-d772ccf88a9c_521x882.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!rTL0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feff7df66-8e36-4b2b-a79e-d772ccf88a9c_521x882.png" width="521" height="882" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/eff7df66-8e36-4b2b-a79e-d772ccf88a9c_521x882.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:882,&quot;width&quot;:521,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:59775,&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://iam.slys.dev/i/177886289?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd316bdc4-2b18-4b6c-89f9-0d46245f667a_548x910.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_!rTL0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feff7df66-8e36-4b2b-a79e-d772ccf88a9c_521x882.png 424w, https://substackcdn.com/image/fetch/$s_!rTL0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feff7df66-8e36-4b2b-a79e-d772ccf88a9c_521x882.png 848w, https://substackcdn.com/image/fetch/$s_!rTL0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feff7df66-8e36-4b2b-a79e-d772ccf88a9c_521x882.png 1272w, https://substackcdn.com/image/fetch/$s_!rTL0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feff7df66-8e36-4b2b-a79e-d772ccf88a9c_521x882.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 role="img" 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><title></title><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_!aOuO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd56db20f-0acd-439e-9617-7a1d8948b410_521x624.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!aOuO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd56db20f-0acd-439e-9617-7a1d8948b410_521x624.png 424w, https://substackcdn.com/image/fetch/$s_!aOuO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd56db20f-0acd-439e-9617-7a1d8948b410_521x624.png 848w, https://substackcdn.com/image/fetch/$s_!aOuO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd56db20f-0acd-439e-9617-7a1d8948b410_521x624.png 1272w, https://substackcdn.com/image/fetch/$s_!aOuO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd56db20f-0acd-439e-9617-7a1d8948b410_521x624.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!aOuO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd56db20f-0acd-439e-9617-7a1d8948b410_521x624.png" width="521" height="624" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d56db20f-0acd-439e-9617-7a1d8948b410_521x624.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:624,&quot;width&quot;:521,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:47620,&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://iam.slys.dev/i/177886289?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1c9b26c-d14c-4493-ab99-42c75c9f779b_545x908.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_!aOuO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd56db20f-0acd-439e-9617-7a1d8948b410_521x624.png 424w, https://substackcdn.com/image/fetch/$s_!aOuO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd56db20f-0acd-439e-9617-7a1d8948b410_521x624.png 848w, https://substackcdn.com/image/fetch/$s_!aOuO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd56db20f-0acd-439e-9617-7a1d8948b410_521x624.png 1272w, https://substackcdn.com/image/fetch/$s_!aOuO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd56db20f-0acd-439e-9617-7a1d8948b410_521x624.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 role="img" 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><title></title><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>Finally, another <strong>Data Table Node</strong> saves everything back into <code>My Substack Posts</code>. The operation is set to <em>upsert</em>, ensuring no duplicates and perfect continuity. The mapping looks like this:</p><ul><li><p><code>post_id</code>: from <code>id</code></p></li><li><p><code>post_title</code>: from <code>title</code></p></li><li><p><code>post_link</code>: conditional <code>https://</code> + <code>url</code></p></li><li><p><code>description</code>: from <code>description</code></p></li><li><p><code>post_date</code>: from <code>postDate</code></p></li><li><p><code>content</code>: from full <code>markdown</code></p></li></ul><p>By the end, I have a clean, living archive of my longform writing - no duplicates, no gaps, no friction. Each node here plays a tiny role, but together, they build the bridge between creativity and structure.</p>
      <p>
          <a href="https://iam.slys.dev/p/how-you-can-automate-sharing-your">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[✨ Real-world agent benchmarks, interpretable TSP solvers, and time-series foundation models]]></title><description><![CDATA[AI Alert]]></description><link>https://iam.slys.dev/p/real-world-agent-benchmarks-interpretable</link><guid isPermaLink="false">https://iam.slys.dev/p/real-world-agent-benchmarks-interpretable</guid><dc:creator><![CDATA[Jakub Slys 🤖]]></dc:creator><pubDate>Wed, 05 Nov 2025 19:20:05 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!MhhN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf4912e3-a4ae-483d-9496-9a1197aba249_1536x1024.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_!MhhN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf4912e3-a4ae-483d-9496-9a1197aba249_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MhhN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf4912e3-a4ae-483d-9496-9a1197aba249_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!MhhN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf4912e3-a4ae-483d-9496-9a1197aba249_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!MhhN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf4912e3-a4ae-483d-9496-9a1197aba249_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!MhhN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf4912e3-a4ae-483d-9496-9a1197aba249_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!MhhN!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf4912e3-a4ae-483d-9496-9a1197aba249_1536x1024.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/af4912e3-a4ae-483d-9496-9a1197aba249_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2292587,&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://iam.slys.dev/i/178065494?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf4912e3-a4ae-483d-9496-9a1197aba249_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!MhhN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf4912e3-a4ae-483d-9496-9a1197aba249_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!MhhN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf4912e3-a4ae-483d-9496-9a1197aba249_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!MhhN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf4912e3-a4ae-483d-9496-9a1197aba249_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!MhhN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf4912e3-a4ae-483d-9496-9a1197aba249_1536x1024.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 role="img" 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><title></title><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>Here&#8217;s a quick rundown of the key trends in Machine Learning research from the last week.</p><div class="poll-embed" data-attrs="{&quot;id&quot;:400831}" data-component-name="PollToDOM"></div><h1>&#128171; Key Research Trends Last Week</h1><p>A focused week spotlighting practical agent evaluation, mechanistic interpretability for optimization, and versatile time-series representations.</p><ul><li><p>Real-world agent capability checks arrive via the new Remote Labor Index, showing current agents perform near the floor on economically valuable remote-work tasks<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a>.</p></li><li><p>Mechanistic interpretability reaches operations research: sparse autoencoders reveal convex-hull, clustering, and separator features inside a Transformer TSP solver<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a>.</p></li><li><p>Pre-trained forecasting models double as strong zero-shot feature extractors, matching or beating specialized classifiers for time-series classification<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a>.</p></li></ul><h1>&#128302;Future Research Directions</h1><p>Expect rapid iteration on benchmarks and methods that connect ML capabilities to real economic and scientific tasks.</p><ul><li><p>Task-grounded agent workflows: better planning, tool use, and evaluation protocols to raise end-to-end performance on realistic projects.</p></li><li><p>Transparent optimization models: expanding mechanistic tools from TSP to routing, scheduling, and planning for hybrid neural&#8211;algorithmic systems.</p></li><li><p>Unified time-series FMs: shared embeddings for forecasting, classification, and anomaly detection with stronger cross-domain generalization.</p></li></ul><p>In short, researchers are stress-testing agents on real jobs, opening the black boxes of optimization models, and reusing forecasting pretraining to power versatile time-series classifiers.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/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">slys.dev 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><h2><strong>What to watch next:</strong></h2><ul><li><p>New agent benchmarks, baselines, and tool-augmented strategies evaluated on open, economically grounded task suites.</p></li><li><p>Interpretability libraries and leaderboards targeting non-language models (e.g., combinatorial optimization, control).</p></li><li><p>Releases of pre-trained time-series models and broader evaluations across healthcare, finance, and industrial telemetry.</p></li></ul><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p><a href="https://arxiv.org/abs/2510.26787v1">Remote Labor Index: Measuring AI Automation of Remote Work</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p><a href="https://arxiv.org/abs/2510.21693v1">Mechanistic Interpretability for Neural TSP Solvers</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p><a href="https://arxiv.org/abs/2510.26777v1">Pre-trained Forecasting Models: Strong Zero-Shot Feature Extractors for Time Series Classification</a></p><p></p></div></div>]]></content:encoded></item><item><title><![CDATA[Why we need Queues - and what they do when no one is watching]]></title><description><![CDATA[System design fundamentals]]></description><link>https://iam.slys.dev/p/why-we-need-queues-and-what-they</link><guid isPermaLink="false">https://iam.slys.dev/p/why-we-need-queues-and-what-they</guid><dc:creator><![CDATA[Jakub Slys 🤖]]></dc:creator><pubDate>Mon, 20 Oct 2025 19:36:37 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!7VBW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F363c62ab-b641-44da-a18a-10599779b3be_1536x1024.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_!7VBW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F363c62ab-b641-44da-a18a-10599779b3be_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7VBW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F363c62ab-b641-44da-a18a-10599779b3be_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!7VBW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F363c62ab-b641-44da-a18a-10599779b3be_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!7VBW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F363c62ab-b641-44da-a18a-10599779b3be_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!7VBW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F363c62ab-b641-44da-a18a-10599779b3be_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7VBW!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F363c62ab-b641-44da-a18a-10599779b3be_1536x1024.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/363c62ab-b641-44da-a18a-10599779b3be_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:3532533,&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://iam.slys.dev/i/176313553?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F363c62ab-b641-44da-a18a-10599779b3be_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!7VBW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F363c62ab-b641-44da-a18a-10599779b3be_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!7VBW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F363c62ab-b641-44da-a18a-10599779b3be_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!7VBW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F363c62ab-b641-44da-a18a-10599779b3be_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!7VBW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F363c62ab-b641-44da-a18a-10599779b3be_1536x1024.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 role="img" 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><title></title><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="pullquote"><p>Imagine you&#8217;re building an online store.<br>Everything runs smoothly - until Black Friday hits.<br>At 10:00 AM, the servers start <strong>sweating</strong>. Every &#8220;<em>Buy Now</em>&#8221; click becomes a request <strong>screaming</strong> for immediate attention.<br>The system can&#8217;t keep up. The queues form&#8230; except this time, not in code - in the minds of frustrated users.<br><strong>The fix?</strong> Queues. But not the human kind - the kind your system understands.</p></div><p>The scene above might feel dramatic, but it&#8217;s a reality for many systems under sudden load. Before diving into definitions, <strong>feel</strong> the pain: overloaded servers, timeouts, and angry customers. In these moments, message queues emerge as unsung heroes. This article explores <em>why</em> we need queues and <em>what they do behind the scenes</em> when no one&#8217;s watching.</p><div><hr></div><p><strong>&#128640; Love learning how real-world systems survive chaos?</strong></p><p>Get more developer-friendly deep dives like this - delivered right to your inbox.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h2>&#128269; Why queues exist</h2><p>In modern distributed systems, different components rarely work at the exact same speed or capacity. Workloads are often <strong>uneven</strong> - sometimes a surge of tasks comes in all at once (like our Black Friday sale), other times it&#8217;s quiet. Often, an upstream <strong>producer</strong> creates work faster than the downstream <strong>consumer</strong> can process.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a> Without intervention, this mismatch leads to backlogs, slowdowns, or outright failures.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LZND!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27cd414c-5e28-44b8-a050-22a2ec9d7e91_1522x547.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LZND!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27cd414c-5e28-44b8-a050-22a2ec9d7e91_1522x547.jpeg 424w, https://substackcdn.com/image/fetch/$s_!LZND!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27cd414c-5e28-44b8-a050-22a2ec9d7e91_1522x547.jpeg 848w, https://substackcdn.com/image/fetch/$s_!LZND!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27cd414c-5e28-44b8-a050-22a2ec9d7e91_1522x547.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!LZND!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27cd414c-5e28-44b8-a050-22a2ec9d7e91_1522x547.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LZND!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27cd414c-5e28-44b8-a050-22a2ec9d7e91_1522x547.jpeg" width="1200" height="431.04395604395603" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/27cd414c-5e28-44b8-a050-22a2ec9d7e91_1522x547.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:523,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:83587,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176313553?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27cd414c-5e28-44b8-a050-22a2ec9d7e91_1522x547.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!LZND!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27cd414c-5e28-44b8-a050-22a2ec9d7e91_1522x547.jpeg 424w, https://substackcdn.com/image/fetch/$s_!LZND!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27cd414c-5e28-44b8-a050-22a2ec9d7e91_1522x547.jpeg 848w, https://substackcdn.com/image/fetch/$s_!LZND!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27cd414c-5e28-44b8-a050-22a2ec9d7e91_1522x547.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!LZND!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27cd414c-5e28-44b8-a050-22a2ec9d7e91_1522x547.jpeg 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 role="img" 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><title></title><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 <strong>message queue</strong> exists to handle this mismatch. Think of it as a <strong>safety buffer</strong> or shock absorber in your architecture. The producer can toss tasks into the queue as fast as needed, and the consumer will pull them out as fast as <em>it</em> can handle. The queue quietly holds onto the overflow - letting the rest of the system breathe. It&#8217;s like a waiting room in a hospital - it doesn&#8217;t make the doctor faster, but it keeps the hallway calm. In other words:</p><div class="pullquote"><p>A queue is like a hospital waiting room - patients (tasks) sit and wait their turn. It doesn&#8217;t help the doctor finish sooner, but it prevents a chaotic pileup at the doctor&#8217;s door.</p></div><p>By absorbing rapid bursts of work, queues <strong>prevent system chaos</strong>. They smooth out traffic spikes by buffering messages until the consumer is ready.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a> This means your system is less likely to crumble under a peak load &#8211; instead, it <em>queues</em> excess work for later processing. Users get faster initial responses (even if some work happens in the background), and your services get a chance to catch up.</p><h1>&#9881;&#65039; How Queues actually work</h1><p>So, what <strong>exactly</strong> does a queue do behind the scenes? At its core, a message queue is a storage area for messages (tasks, data, requests - any work units). One part of your system (the <strong>producer</strong>) sends messages into the queue. Another part (the <strong>consumer</strong>) picks them up and does the processing, often asynchronously.</p><p>Let&#8217;s break down a message&#8217;s journey in a typical queue system.</p><ol><li><p><strong>Produced:</strong> A producer application sends a message to the queue (e.g., &#8220;<code>New Order #12345</code>&#8221;).</p></li><li><p><strong>Queued:</strong> The message sits in the queue, waiting its turn. (This is the &#8220;<em>buffer</em>&#8221; period - potentially microseconds or hours, depending on system load).</p></li><li><p><strong>Consumed:</strong> A consumer application retrieves the message from the queue and begins processing the order. Importantly, no other consumer will get this message at the same time.</p></li><li><p><strong>Acknowledged:</strong> Once processed, the consumer sends an acknowledgment to the queue. The queue can then remove the message, knowing it&#8217;s been handled successfully.</p></li></ol><p>This flow turns a system from <strong>&#8220;</strong><em><strong>do it now</strong></em><strong>&#8221;</strong> into <strong>&#8220;</strong><em><strong>do it when you&#8217;re ready</strong></em><strong>&#8221;.</strong> By inserting that waiting period, the producer isn&#8217;t blocking on the task being done - it can move on to other things, confident the queue will eventually deliver the work to a consumer.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vFUq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3bdc91b-a10c-4b1f-94b8-4300a6372e1c_1449x686.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vFUq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3bdc91b-a10c-4b1f-94b8-4300a6372e1c_1449x686.jpeg 424w, https://substackcdn.com/image/fetch/$s_!vFUq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3bdc91b-a10c-4b1f-94b8-4300a6372e1c_1449x686.jpeg 848w, https://substackcdn.com/image/fetch/$s_!vFUq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3bdc91b-a10c-4b1f-94b8-4300a6372e1c_1449x686.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!vFUq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3bdc91b-a10c-4b1f-94b8-4300a6372e1c_1449x686.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vFUq!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3bdc91b-a10c-4b1f-94b8-4300a6372e1c_1449x686.jpeg" width="1200" height="568.1159420289855" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f3bdc91b-a10c-4b1f-94b8-4300a6372e1c_1449x686.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:686,&quot;width&quot;:1449,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:102139,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176313553?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3bdc91b-a10c-4b1f-94b8-4300a6372e1c_1449x686.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!vFUq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3bdc91b-a10c-4b1f-94b8-4300a6372e1c_1449x686.jpeg 424w, https://substackcdn.com/image/fetch/$s_!vFUq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3bdc91b-a10c-4b1f-94b8-4300a6372e1c_1449x686.jpeg 848w, https://substackcdn.com/image/fetch/$s_!vFUq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3bdc91b-a10c-4b1f-94b8-4300a6372e1c_1449x686.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!vFUq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3bdc91b-a10c-4b1f-94b8-4300a6372e1c_1449x686.jpeg 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 role="img" 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><title></title><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>The diagram above is the simplest view: the producer puts messages in one side, and the consumer takes them out the other. <strong>Decoupling</strong> is the magic here. The producer and consumer don&#8217;t interact directly; they communicate via the queue. If the consumer is slow or temporarily offline, the messages just pile up in the queue - the producer doesn&#8217;t need to slow down or fail in the meantime. Conversely, if the producer slows down, the consumer can continue working on whatever is in the queue.</p><p>To illustrate with a snippet of (simplified) Python-like pseudo-code:</p><pre><code><code># Producer sends a message (e.g., an order request) to the queue.
queue.send(order_request)  

# ... time passes, message waits in the queue ...

# Consumer fetches the next message from the queue when ready.
order_request = queue.receive()
process(order_request)
queue.acknowledge(order_request)  # confirm the message was processed
</code></code></pre><p>In a real system, the <strong>queue server</strong> (broker) marks the message as &#8220;<em>invisible</em>&#8221; for others once a consumer picks it up. After processing, the consumer <em>acknowledges</em> it. If the consumer fails to acknowledge (say it crashed), the message becomes visible in the queue again after a timeout, so it can be retried.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a> This guarantees that every message will eventually be handled, even if something goes wrong mid-process.</p><div class="pullquote"><p>This tiny shift - using a queue - makes a system <strong>asynchronous</strong>. The producer no longer waits for the work to finish. It just drops a message and moves on. The system becomes more flexible: tasks get done <em>when there&#8217;s capacity</em>, rather than all &#8220;right now&#8221; at once.</p></div><h1>&#128165; Life without Queues</h1><p>What happens if you <strong>don&#8217;t</strong> have a queue in situations of uneven load? In short, <em>chaos</em>. Let&#8217;s paint the picture: suppose your <strong>Payment Service</strong> calls the <strong>Shipping Service</strong> directly for each order. It works fine under light load. But one day, orders flood in:</p><ul><li><p>If Shipping slows down or (gasp!) goes down, Payment is stuck waiting. Users clicking &#8220;<em>Pay</em>&#8221; start seeing spinners or errors. The payment calls fail because the downstream service isn&#8217;t responding.</p></li><li><p>As traffic increases, Payment and Shipping form a tight chain. The slowest component dictates the system&#8217;s speed. Users who click faster than Shipping can handle end up queuing in their browsers - or giving up.</p></li><li><p>Even worse, a failure cascades. If Shipping crashes under load, it <strong>takes Payment down with it</strong>. A single point of failure can ripple outward, causing a domino effect.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a></p></li></ul><p>This is the <em>bottleneck of doom</em> that tightly coupled systems face. Every component must be up and fast for the whole flow to work. In a <strong>synchronous call</strong> setup, Service A is blocked until Service B finishes. If B fails, A fails; if B is slow, A is slow. It&#8217;s brittle and dangerous, especially as you add more services into the mix.</p><p>Now contrast that with a queue-based approach (the <strong>asynchronous solution</strong>). Payment would post an &#8220;<em>Order placed</em>&#8221; message to a queue. Shipping will pick up orders from the queue at its own pace. If Shipping is down, orders just stay in the queue for a bit; Payment doesn&#8217;t crash - it can continue taking orders. When Shipping comes back, it processes the backlog. In the meantime, customers checked out successfully - maybe with a note &#8220;<em>We&#8217;ll email your tracking info soon</em>&#8221;, but the site stays <strong>running</strong>.</p><p>By inserting a queue, you <strong>decouple the pace</strong> of different components. Each part can <strong>fail independently</strong> without bringing the whole system down. The result is a more resilient architecture: one that degrades gracefully instead of exploding under stress.</p><div class="pullquote"><p><em>Synchronous calls create brittle systems that fail together, while asynchronous messaging creates resilient systems that fail independently. In other words, message queues are your decoupling superpower.</em></p></div><h1>&#129518; Queues in practice - RabbitMQ, Kafka &amp; Friends</h1><p>All this theory is great, but how do we implement queues in the real world? There are many messaging tools and services out there. Here are a few popular ones, each with its own flavor:</p><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/ssTbh/1/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c46e6044-3c40-4f48-b4c9-694081343a86_1220x622.png&quot;,&quot;thumbnail_url_full&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/de94811b-8c29-4488-88f2-69969511fbf6_1220x692.png&quot;,&quot;height&quot;:282,&quot;title&quot;:&quot;Popular messaging systems&quot;,&quot;description&quot;:&quot;&quot;}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/ssTbh/1/" width="730" height="282" frameborder="0" scrolling="no"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><p><strong>RabbitMQ</strong> is a traditional message broker that implements the AMQP protocol. It excels at <strong>reliable delivery</strong> and complex routing (topics, fan-out, etc.), ensuring messages get to the right place. For example, you might use RabbitMQ to queue tasks for sending emails: each email request is a message, and a pool of consumers sends them out one by one, guaranteeing none are lost.</p><p><strong>Kafka</strong>, on the other hand, is often described as a &#8220;<em>distributed commit log</em>&#8221;. It&#8217;s great for streaming large volumes of data (think millions of events per minute). Kafka retains ordered logs of events, and consumers track their <strong>offset</strong> (position) in the log as they go. It&#8217;s perfect for systems where you replay or process event histories and need high scalability.</p><p>Cloud services like <strong>Amazon SQS</strong> and <strong>Google Pub/Sub</strong> offer queueing as a service. You don&#8217;t install anything - you just use their API. They automatically scale and are highly reliable. These are great when you need a queue but prefer the cloud provider handle the dirty work (maintenance, scaling, fault tolerance). For instance, SQS guarantees <em>at-least-once</em> delivery of messages and provides features like <strong>dead-letter queues</strong> out of the box. Similarly, Pub/Sub on GCP handles fan-out messaging to multiple subscribers easily.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qEYb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c138e98-efb6-423d-8a5f-8ec01bd08a20_1340x1093.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qEYb!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c138e98-efb6-423d-8a5f-8ec01bd08a20_1340x1093.jpeg 424w, https://substackcdn.com/image/fetch/$s_!qEYb!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c138e98-efb6-423d-8a5f-8ec01bd08a20_1340x1093.jpeg 848w, https://substackcdn.com/image/fetch/$s_!qEYb!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c138e98-efb6-423d-8a5f-8ec01bd08a20_1340x1093.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!qEYb!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c138e98-efb6-423d-8a5f-8ec01bd08a20_1340x1093.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qEYb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c138e98-efb6-423d-8a5f-8ec01bd08a20_1340x1093.jpeg" width="1340" height="1093" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5c138e98-efb6-423d-8a5f-8ec01bd08a20_1340x1093.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1093,&quot;width&quot;:1340,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:101670,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176313553?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c138e98-efb6-423d-8a5f-8ec01bd08a20_1340x1093.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!qEYb!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c138e98-efb6-423d-8a5f-8ec01bd08a20_1340x1093.jpeg 424w, https://substackcdn.com/image/fetch/$s_!qEYb!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c138e98-efb6-423d-8a5f-8ec01bd08a20_1340x1093.jpeg 848w, https://substackcdn.com/image/fetch/$s_!qEYb!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c138e98-efb6-423d-8a5f-8ec01bd08a20_1340x1093.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!qEYb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c138e98-efb6-423d-8a5f-8ec01bd08a20_1340x1093.jpeg 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 role="img" 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><title></title><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>Each of these &#8220;<em>friends</em>&#8221; has its nuances, but all share the same core idea: <strong>don&#8217;t call services directly; instead, communicate via an intermediary queue.</strong> As one engineer put it:</p><div class="pullquote"><p>Queues don&#8217;t just move data - they set the <strong>rhythm</strong> of your system.</p></div><p>By buffering and dispatching messages, queues essentially dictate <strong>when</strong> each part of the system gets to work, acting like a conductor in an orchestra. The result is a more harmonious (and resilient) performance.</p><h1>&#129504; Key concepts to know</h1><p>Before you run off to implement your own queue, let&#8217;s demystify some jargon you&#8217;ll encounter. Here&#8217;s a quick glossary of queue concepts:</p><p><strong>Consumer Group.</strong> A set of consumers <em>collaborating</em> on the same queue or topic. In a consumer group, each message is delivered to only one member of the group.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a> This is how you scale out processing - e.g., three consumers in a group can divide the work of one queue. (Kafka uses consumer groups heavily for parallelism.)</p><p><strong>Offset.</strong> A marker of how far a consumer has read in the queue. Think of it as a <strong>bookmark</strong> in a stream of messages. For example, Kafka assigns each message a sequential offset number; a consumer&#8217;s position (last processed offset) tells it where to resume next time.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-6" href="#footnote-6" target="_self">6</a> Offsets prevent re-reading from the start every time and help with recovery (you know what&#8217;s been processed).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!j8V9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9fb8c6d1-fb71-4f94-aa6b-51a2289627fd_1481x830.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!j8V9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9fb8c6d1-fb71-4f94-aa6b-51a2289627fd_1481x830.jpeg 424w, https://substackcdn.com/image/fetch/$s_!j8V9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9fb8c6d1-fb71-4f94-aa6b-51a2289627fd_1481x830.jpeg 848w, https://substackcdn.com/image/fetch/$s_!j8V9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9fb8c6d1-fb71-4f94-aa6b-51a2289627fd_1481x830.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!j8V9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9fb8c6d1-fb71-4f94-aa6b-51a2289627fd_1481x830.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!j8V9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9fb8c6d1-fb71-4f94-aa6b-51a2289627fd_1481x830.jpeg" width="1456" height="816" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9fb8c6d1-fb71-4f94-aa6b-51a2289627fd_1481x830.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:816,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:92004,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176313553?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9fb8c6d1-fb71-4f94-aa6b-51a2289627fd_1481x830.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!j8V9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9fb8c6d1-fb71-4f94-aa6b-51a2289627fd_1481x830.jpeg 424w, https://substackcdn.com/image/fetch/$s_!j8V9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9fb8c6d1-fb71-4f94-aa6b-51a2289627fd_1481x830.jpeg 848w, https://substackcdn.com/image/fetch/$s_!j8V9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9fb8c6d1-fb71-4f94-aa6b-51a2289627fd_1481x830.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!j8V9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9fb8c6d1-fb71-4f94-aa6b-51a2289627fd_1481x830.jpeg 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 role="img" 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><title></title><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>Dead-letter Queue (</strong><em><strong>DLQ</strong></em><strong>).</strong> A special queue where messages go when they <strong>fail</strong> repeatedly. If a message can&#8217;t be processed after X tries (due to errors, etc.), it&#8217;s often routed to a dead-letter queue rather than clogging the main queue. Think of it as the &#8220;<em>rejects</em>&#8221; bin for problematic messages - they can be inspected or retried later without affecting the primary flow.</p><p><strong>Ack (Acknowledgment).</strong> A signal from consumer to queue that &#8220;<em>I got the message and handled it</em>&#8221;. For example, in RabbitMQ a consumer sends an ACK after processing, so the broker knows it can remove that message from the queue. If no ack is received (perhaps the consumer died), the message is requeued or made visible again. Acknowledgements prevent data loss by ensuring work isn&#8217;t dropped even if something goes wrong mid-processing.</p><p>These concepts help ensure your queue-based system runs smoothly. For instance, using consumer groups means you can scale out processing while each message is still handled only once. Dead-letter queues ensure you don&#8217;t get stuck on a poison message that can&#8217;t be processed - it gets set aside for later analysis. And acknowledgments combined with offsets give reliability: they guarantee that work is either done <em>at least once</em> or the system knows to retry it.</p><h1>&#129513; How Queues protect systems from overload</h1><p>One of the biggest advantages of queues is how they shield your system from <strong>overload</strong>. By their very nature, queues introduce a form of <strong>backpressure</strong>. This means when the intake of work is faster than the output, the work doesn&#8217;t break the system - it simply accumulates in the queue. The system as a whole slows down <strong>gracefully</strong> instead of crashing.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4QEp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd629c730-fb89-492d-8e9f-1314b3e28476_1488x732.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4QEp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd629c730-fb89-492d-8e9f-1314b3e28476_1488x732.jpeg 424w, https://substackcdn.com/image/fetch/$s_!4QEp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd629c730-fb89-492d-8e9f-1314b3e28476_1488x732.jpeg 848w, https://substackcdn.com/image/fetch/$s_!4QEp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd629c730-fb89-492d-8e9f-1314b3e28476_1488x732.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!4QEp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd629c730-fb89-492d-8e9f-1314b3e28476_1488x732.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4QEp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd629c730-fb89-492d-8e9f-1314b3e28476_1488x732.jpeg" width="1456" height="716" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d629c730-fb89-492d-8e9f-1314b3e28476_1488x732.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:716,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:84792,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176313553?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd629c730-fb89-492d-8e9f-1314b3e28476_1488x732.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!4QEp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd629c730-fb89-492d-8e9f-1314b3e28476_1488x732.jpeg 424w, https://substackcdn.com/image/fetch/$s_!4QEp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd629c730-fb89-492d-8e9f-1314b3e28476_1488x732.jpeg 848w, https://substackcdn.com/image/fetch/$s_!4QEp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd629c730-fb89-492d-8e9f-1314b3e28476_1488x732.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!4QEp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd629c730-fb89-492d-8e9f-1314b3e28476_1488x732.jpeg 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 role="img" 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><title></title><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 message queue can act as a traffic buffer. In the left graph, incoming requests fluctuate wildly, sometimes exceeding what the system can handle. On the right, after introducing a queue, the processing rate stays steady and within safe limits, smoothing out the spikes. The backlog accumulates temporarily in the queue, protecting the consumer service.</p><p>Let&#8217;s revisit our online store example. Without a queue, a surge of 1000 orders in a minute might overwhelm the order processing service, leading to errors or a crash. With a queue in place, those 1000 order messages are all accepted quickly into the queue (so the users&#8217; checkout experience is fast), and then the orders are pulled out one by one (or a few at a time) by the processing service. The service might only handle, say, 100 orders per minute, but that&#8217;s okay - it will work through the backlog over the next 10 minutes. <strong>Importantly, the front-end doesn&#8217;t collapse under the spike</strong>.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-7" href="#footnote-7" target="_self">7</a> It absorbed the burst, and the system remains stable (albeit with a slight delay in processing).</p><p>This is the essence of <strong>load leveling</strong>. Queues level out the peaks and troughs of traffic. During a traffic spike, the queue grows longer (acting as a buffer). During quieter times, the queue drains as consumers catch up. The average rate of processing can remain stable even if the incoming rate is jagged. It&#8217;s much easier to design a system for a steady 100 orders/min than to design for sudden bursts of 1000/min followed by zero/minute lulls.</p><p>A real-world use case: <strong>E-commerce checkout.</strong> When a customer places an order, the website immediately puts an &#8220;<em>Order Placed</em>&#8221; message onto a queue and instantly confirms to the user (&#8220;<em>Thank you, your order is received!</em>&#8221;). Downstream, an Order Processing service will take messages from the queue and actually process payments, update inventory, notify shipping, etc. If there&#8217;s a Black Friday rush, the order confirmations still happen instantly (queue accepts them), and the processing service works through them as fast as it can. The user experience is preserved - the site stays responsive - even if actual fulfillment is a bit behind the scenes.</p><p>Another example: <strong>Email sending.</strong> Suppose your app needs to send thousands of emails (like newsletters or notifications). If you try to send 10,000 emails all at once, your email server (SMTP) or third-party API might choke (or rate-limit you). Instead, you put email requests into a queue. A worker service pulls, say, 50 emails per second from the queue and sends them. This naturally <strong>throttles</strong> the outflow to a rate the email server can handle. You never suddenly dump 10k requests; you trickle them. The queue ensures no email is lost, just sent a bit later if needed. The system remains stable and you avoid flooding any component.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Bdqf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce646062-cd93-4bd3-96a1-2619cf6c4786_1366x990.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Bdqf!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce646062-cd93-4bd3-96a1-2619cf6c4786_1366x990.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Bdqf!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce646062-cd93-4bd3-96a1-2619cf6c4786_1366x990.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Bdqf!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce646062-cd93-4bd3-96a1-2619cf6c4786_1366x990.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Bdqf!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce646062-cd93-4bd3-96a1-2619cf6c4786_1366x990.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Bdqf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce646062-cd93-4bd3-96a1-2619cf6c4786_1366x990.jpeg" width="1366" height="990" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ce646062-cd93-4bd3-96a1-2619cf6c4786_1366x990.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:990,&quot;width&quot;:1366,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:101865,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176313553?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce646062-cd93-4bd3-96a1-2619cf6c4786_1366x990.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Bdqf!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce646062-cd93-4bd3-96a1-2619cf6c4786_1366x990.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Bdqf!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce646062-cd93-4bd3-96a1-2619cf6c4786_1366x990.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Bdqf!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce646062-cd93-4bd3-96a1-2619cf6c4786_1366x990.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Bdqf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce646062-cd93-4bd3-96a1-2619cf6c4786_1366x990.jpeg 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 role="img" 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><title></title><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>In summary, queues act as a <strong>buffer zone</strong> between the fast and slow parts of your system. Producers can run at full blast, confident that if consumers can&#8217;t keep up immediately, the work will simply wait its turn. Instead of erroring out or crashing under overload, the system&#8217;s heartbeat just goes a bit slower. All components operate at their <strong>own optimal pace</strong>, and the queue handles the hand-off.</p><div class="pullquote"><p><em>Of course, if producers permanently outpace consumers, a queue isn&#8217;t a magic infinite bucket - eventually it will fill up or messages will wait so long they become irrelevant. We&#8217;ll address those pitfalls next.</em></p></div><h1>&#9888;&#65039; The dark side of Queues</h1><p>Queues are powerful, but like any tool they come with <strong>trade-offs and pitfalls</strong>. It&#8217;s important to be aware of these &#8220;<em>dark side</em>&#8221; aspects so you can design your systems to handle them.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_pLP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd550c3ba-a906-46a8-96b0-4bfc5314f2b2_1243x1085.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_pLP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd550c3ba-a906-46a8-96b0-4bfc5314f2b2_1243x1085.jpeg 424w, https://substackcdn.com/image/fetch/$s_!_pLP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd550c3ba-a906-46a8-96b0-4bfc5314f2b2_1243x1085.jpeg 848w, https://substackcdn.com/image/fetch/$s_!_pLP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd550c3ba-a906-46a8-96b0-4bfc5314f2b2_1243x1085.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!_pLP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd550c3ba-a906-46a8-96b0-4bfc5314f2b2_1243x1085.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_pLP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd550c3ba-a906-46a8-96b0-4bfc5314f2b2_1243x1085.jpeg" width="1243" height="1085" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d550c3ba-a906-46a8-96b0-4bfc5314f2b2_1243x1085.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1085,&quot;width&quot;:1243,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:110759,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176313553?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd550c3ba-a906-46a8-96b0-4bfc5314f2b2_1243x1085.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!_pLP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd550c3ba-a906-46a8-96b0-4bfc5314f2b2_1243x1085.jpeg 424w, https://substackcdn.com/image/fetch/$s_!_pLP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd550c3ba-a906-46a8-96b0-4bfc5314f2b2_1243x1085.jpeg 848w, https://substackcdn.com/image/fetch/$s_!_pLP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd550c3ba-a906-46a8-96b0-4bfc5314f2b2_1243x1085.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!_pLP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd550c3ba-a906-46a8-96b0-4bfc5314f2b2_1243x1085.jpeg 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 role="img" 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><title></title><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>Message duplication.</strong> Many queue systems (for example, cloud queues like SQS) guarantee <em>at-least-once</em> delivery. This means it&#8217;s possible the same message will be delivered twice on rare occasions. Network hiccups or crashes might make a consumer appear to not have processed a message, so the broker redelivers it, and you end up doing the task twice. The solution is to design idempotent consumers &#8211; in plain terms, make sure that processing a message twice has the same effect as once. For instance, if the message says &#8220;<em>ship </em><code>Order #123</code>&#8221;, your shipping service should check if <code>Order #123</code> was already shipped before doing it again. <em>Assume duplicates will happen</em>, and guard against any harmful side effects.</p><p><strong>Lag and latency.</strong> A queue can <strong>delay</strong> processing. If your queue grows very long (say, millions of messages), some messages might not get processed for a long time. In extreme cases, this could violate user expectations (imagine if an order confirmation email arrives 3 days late). Long queues also mean more memory/disk usage and potentially timeouts if messages become too old. In practice, if you see queue lengths growing without bound, it&#8217;s a sign your consumers are consistently too slow for the incoming workload &#8211; you either need more consumers, faster processing, or to throttle the producers (see <strong>flow control</strong>). Also consider message TTL (time-to-live) for things that have an expiry, or implementing backpressure to inform producers to slow down when queues are too full.</p><p><strong>Ordering challenges.</strong> Queues often don&#8217;t guarantee that messages will be processed in the exact order they were sent, especially when you have multiple consumers or partitions. For example, if two messages A and B are sent, it&#8217;s possible B might get processed before A in some setups (unless the queue is strictly FIFO). Even with a single queue, if a message fails and retries, it might be handled out of sequence. If order matters (say, two updates to the same user&#8217;s profile), you have to design for it &#8211; either use ordering keys/FIFO queues or ensure each message is independent. In distributed systems, once you introduce parallel consumers, <strong>ordering is not guaranteed</strong> by default. You may need to enforce ordering in the consumer logic or restrict certain flows to a single consumer.</p><p><strong>Visibility timeouts and reprocessing.</strong> When a consumer takes a message from a queue, that message is often hidden (invisible) from others for a <strong>visibility timeout</strong> period. If the consumer fails to acknowledge before this timeout, the message pops back onto the queue for someone else to retry. This is great for reliability, but it means your system must tolerate the same message being processed more than once in parallel or sequentially. Also, if a task truly <em>always</em> fails (e.g., bad data), it could get stuck in a cycle of being redelivered over and over. That&#8217;s where the earlier mentioned <strong>dead-letter queue</strong> is important - after a few failed attempts, send the message to a DLQ so you can investigate it without blocking the main queue.</p><p>In short, <strong>queues require discipline</strong>. You gain resilience and flexibility, but you also inherit the complexities of an asynchronous system. Monitoring becomes key: you&#8217;ll want alerts if queues are backing up too much (indicative of a problem). You&#8217;ll need strategies for poison messages (DLQs) and duplicate handling (<em>idempotency</em>). Ordering might need extra attention if it&#8217;s critical to your application&#8217;s correctness.</p><div><hr></div><p><strong>&#129504; What&#8217;s your take on the dark side? Ever wrestled with duplicate messages or visibility timeouts?</strong></p><p>I&#8217;d love to hear your war stories or wins - let&#8217;s chat below.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/why-we-need-queues-and-what-they/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/why-we-need-queues-and-what-they/comments"><span>Leave a comment</span></a></p><div><hr></div><p>The &#8220;<em>dark side</em>&#8221; isn&#8217;t a reason to avoid queues, but it is a reminder: <strong>power comes with responsibility</strong>. A poorly managed queue can become a black hole (messages languishing forever) or a source of subtle bugs (duplicate processing). With good design and practices, these issues are all manageable.</p><h1>&#128260; How it all connects</h1><p>By introducing queues, many systems find themselves evolving toward an <strong>event-driven architecture (EDA)</strong>. In an event-driven mindset, instead of components calling each other directly (imperative &#8220;<em>do this now</em>&#8221; commands), they emit events (facts about something that <em>happened</em>) and other components react to those events.</p><p>Using queues is often the first step in this direction. You stop asking &#8220;<em>What should happen now in this workflow?</em>&#8221; and start asking &#8220;<em>What just happened, and who cares about it?</em>&#8221; When Payment places an &#8220;<em>Order Placed</em>&#8221; message on a queue, it&#8217;s essentially saying: <em>&#8220;This event occurred&#8221;.</em> Now any service interested in orders (billing, shipping, notifications, analytics) can subscribe to that queue or topic and do its part, <strong>independently</strong>. You can add a new service (say, a <code>ReportingService</code>) later that also listens for &#8220;<em>Order Placed</em>&#8221; events, without touching the Payment or Shipping code at all. This is the essence of <em>loose coupling</em>.</p><p>Over time, a simple queue for point-to-point communication can grow into a <strong>publish/subscribe system</strong> with multiple consumers and producers all interacting via events. Architectures like <strong>microservices</strong> often leverage queues and pub/sub to keep services decoupled and scalable. It&#8217;s a different way of thinking about system design - more like a network of small reactive processes rather than a single big &#8211; program.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!rPxY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb233dd6f-1f07-4a7c-ba4a-c64c68e75c54_1428x1173.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rPxY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb233dd6f-1f07-4a7c-ba4a-c64c68e75c54_1428x1173.jpeg 424w, https://substackcdn.com/image/fetch/$s_!rPxY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb233dd6f-1f07-4a7c-ba4a-c64c68e75c54_1428x1173.jpeg 848w, https://substackcdn.com/image/fetch/$s_!rPxY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb233dd6f-1f07-4a7c-ba4a-c64c68e75c54_1428x1173.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!rPxY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb233dd6f-1f07-4a7c-ba4a-c64c68e75c54_1428x1173.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!rPxY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb233dd6f-1f07-4a7c-ba4a-c64c68e75c54_1428x1173.jpeg" width="1428" height="1173" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b233dd6f-1f07-4a7c-ba4a-c64c68e75c54_1428x1173.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1173,&quot;width&quot;:1428,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:104062,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176313553?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb233dd6f-1f07-4a7c-ba4a-c64c68e75c54_1428x1173.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!rPxY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb233dd6f-1f07-4a7c-ba4a-c64c68e75c54_1428x1173.jpeg 424w, https://substackcdn.com/image/fetch/$s_!rPxY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb233dd6f-1f07-4a7c-ba4a-c64c68e75c54_1428x1173.jpeg 848w, https://substackcdn.com/image/fetch/$s_!rPxY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb233dd6f-1f07-4a7c-ba4a-c64c68e75c54_1428x1173.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!rPxY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb233dd6f-1f07-4a7c-ba4a-c64c68e75c54_1428x1173.jpeg 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 role="img" 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><title></title><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>The beauty is that queues allow your system to <strong>scale and evolve</strong>. Need to handle more load? Add more consumer instances to process from the queue (forming a consumer group). Need to add new functionality? Just plug in a new event handler that listens to relevant queues, instead of rewriting the whole flow. The system becomes a set of building blocks connected by queues (event channels), which can be rearranged or extended with minimal fuss.</p><p>In other words, adopting queues is a gateway to thinking in terms of <strong>events</strong> and <strong>reactions</strong>. It can lead to more robust systems, because each part is isolated - they communicate only via the messages, not by direct assumptions about each other&#8217;s state or timing. This often results in systems that are easier to maintain and expand, as new requirements can be met by adding new message types or consumers rather than modifying existing ones.</p><p>Everything connects: queues, by decoupling components, set the stage for an architecture where <em>everything is an event</em>. And once you go down that path, you might discover your system is not just handling spikes better, but is also more <strong>extensible</strong> and <strong>observable</strong> (since you can monitor the event flow, inspect queues, etc.).</p><h1>&#129517; Closing thoughts</h1><p>Building systems is as much about handling failure and unpredictability as it is about the &#8220;<em>sunny day</em>&#8221; scenarios. Message queues shine in those chaotic moments. They are the <strong>heartbeat</strong> of a distributed system, giving it rhythm and resilience. They absorb bursts of traffic, prevent cascades of failure, and let each component work at its own pace.</p><p>Yes, queues add complexity - you must handle eventual consistency, delayed processing, and other quirks. But the payoff is huge: your services won&#8217;t easily knock each other over like dominoes. As an engineer (especially a beginner), learning to integrate queues is a stepping stone to designing systems that <strong>scale</strong> and <strong>survive</strong> real-world demands.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!342x!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45de334f-0f04-44bb-a0ab-06eaac001efd_1381x564.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!342x!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45de334f-0f04-44bb-a0ab-06eaac001efd_1381x564.jpeg 424w, https://substackcdn.com/image/fetch/$s_!342x!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45de334f-0f04-44bb-a0ab-06eaac001efd_1381x564.jpeg 848w, https://substackcdn.com/image/fetch/$s_!342x!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45de334f-0f04-44bb-a0ab-06eaac001efd_1381x564.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!342x!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45de334f-0f04-44bb-a0ab-06eaac001efd_1381x564.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!342x!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45de334f-0f04-44bb-a0ab-06eaac001efd_1381x564.jpeg" width="1381" height="564" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/45de334f-0f04-44bb-a0ab-06eaac001efd_1381x564.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:564,&quot;width&quot;:1381,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:71495,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/176313553?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45de334f-0f04-44bb-a0ab-06eaac001efd_1381x564.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!342x!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45de334f-0f04-44bb-a0ab-06eaac001efd_1381x564.jpeg 424w, https://substackcdn.com/image/fetch/$s_!342x!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45de334f-0f04-44bb-a0ab-06eaac001efd_1381x564.jpeg 848w, https://substackcdn.com/image/fetch/$s_!342x!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45de334f-0f04-44bb-a0ab-06eaac001efd_1381x564.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!342x!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45de334f-0f04-44bb-a0ab-06eaac001efd_1381x564.jpeg 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 role="img" 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><title></title><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>Ultimately, queues help engineers (and users!) sleep better at night. Instead of dreading the midnight spike or the next big sale, you can be confident your system will bend, not break.</p><div class="pullquote"><p><strong>Queues are the heartbeat of a system.</strong><br>They give rhythm, absorb chaos, and let components breathe at their own pace.<br>Thanks to them, systems stay alive &#8212; and engineers sleep better.</p></div><h1>&#9997;&#65039; Recap</h1><p><strong>What are queues?</strong> A queue is a buffer between components - a place where messages wait so that producers and consumers can work at different speeds. It turns &#8220;<em>immediate</em>&#8221; calls into asynchronous work.</p><p><strong>Why use them?</strong> Queues help with scaling and fault tolerance. They even out traffic spikes (prevent overload), decouple services (one can fail or slow without bringing the other down), and improve resilience and throughput.</p><p><strong>Tools:</strong> There are many implementations - RabbitMQ for robust task queueing, Kafka for high-volume streaming, cloud services like AWS SQS or GCP Pub/Sub for managed simplicity. Use the right tool for your needs (consider factors like throughput, ordering, persistence).</p><p><strong>Challenges:</strong> Queues aren&#8217;t silver bullets. Be mindful of duplicates (use <em>idempotency</em>), potential delays (monitor queue length), ordering issues (design accordingly), and the need for proper error handling (dead-letter queues for poison messages).</p><p><strong>Big picture:</strong> Queues enable <strong>event-driven architectures</strong>. They allow systems to react to events at their own pace and scale out by adding consumers. In exchange, they require a shift in thinking (asynchronous mindset) and careful design.</p><div><hr></div><p><strong>&#128226; Know someone who&#8217;s starting out in backend or devops?</strong></p><p>Share this post and help them understand queues before the queues understand them.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/leaderboard?&amp;utm_source=post&quot;,&quot;text&quot;:&quot;Refer a friend&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/leaderboard?&amp;utm_source=post"><span>Refer a friend</span></a></p><div><hr></div><p>By embracing queues, even a beginner developer can start to solve complex scaling problems with elegance - turning panic into <em>ordered</em> (pun intended) chaos that a system can handle. In short, queues keep the data flowing and the systems going, even when no one&#8217;s watching.</p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p><a href="https://learn.microsoft.com/en-us/azure/architecture/patterns/queue-based-load-leveling">Queue-Based Load Leveling pattern</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p><a href="https://medium.com/red-buffer/demystifying-message-queues-seamless-communication-for-asynchronous-processing-372ebcc9865b">Demystifying Message Queues: Seamless Communication for Asynchronous Processing</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p><a href="https://stackoverflow.com/questions/71391169/do-failed-sqs-messages-have-a-visibility-timeout">Do failed SQS messages have a visibility timeout?</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-4" href="#footnote-anchor-4" class="footnote-number" contenteditable="false" target="_self">4</a><div class="footnote-content"><p><a href="https://medium.com/@kanishks772/learn-system-design-with-me-day-12-message-queue-patterns-e92371d34a7c">Learn System Design With Me. Day 12: Message Queue Patterns</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-5" href="#footnote-anchor-5" class="footnote-number" contenteditable="false" target="_self">5</a><div class="footnote-content"><p><a href="https://learn.microsoft.com/en-us/azure/architecture/patterns/competing-consumers">Competing Consumers pattern</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-6" href="#footnote-anchor-6" class="footnote-number" contenteditable="false" target="_self">6</a><div class="footnote-content"><p><a href="https://docs.confluent.io/kafka/design/consumer-design.html">Kafka Consumer Design: Consumers, Consumer Groups, and Offsets</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-7" href="#footnote-anchor-7" class="footnote-number" contenteditable="false" target="_self">7</a><div class="footnote-content"><p><a href="https://www.enterpriseintegrationpatterns.com/ramblings/queues_flow_control.html">Queues invert control flow but require flow control</a></p><p></p></div></div>]]></content:encoded></item><item><title><![CDATA[Lead smarter in the age of AI]]></title><description><![CDATA[Why every leader needs an AI thinking partner &#8212; and how to build yours today]]></description><link>https://iam.slys.dev/p/lead-smarter-in-the-age-of-ai</link><guid isPermaLink="false">https://iam.slys.dev/p/lead-smarter-in-the-age-of-ai</guid><dc:creator><![CDATA[Jakub Slys 🤖]]></dc:creator><pubDate>Mon, 06 Oct 2025 18:20:08 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!lkit!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbcac4cb-a52e-4c02-b939-8d6c5564a984_1536x1024.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_!lkit!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbcac4cb-a52e-4c02-b939-8d6c5564a984_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lkit!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbcac4cb-a52e-4c02-b939-8d6c5564a984_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!lkit!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbcac4cb-a52e-4c02-b939-8d6c5564a984_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!lkit!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbcac4cb-a52e-4c02-b939-8d6c5564a984_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!lkit!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbcac4cb-a52e-4c02-b939-8d6c5564a984_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!lkit!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbcac4cb-a52e-4c02-b939-8d6c5564a984_1536x1024.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bbcac4cb-a52e-4c02-b939-8d6c5564a984_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2296823,&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://iam.slys.dev/i/174819107?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbcac4cb-a52e-4c02-b939-8d6c5564a984_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!lkit!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbcac4cb-a52e-4c02-b939-8d6c5564a984_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!lkit!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbcac4cb-a52e-4c02-b939-8d6c5564a984_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!lkit!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbcac4cb-a52e-4c02-b939-8d6c5564a984_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!lkit!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbcac4cb-a52e-4c02-b939-8d6c5564a984_1536x1024.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 role="img" 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><title></title><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="pullquote"><p>It&#8217;s 10:47 PM, you&#8217;re staring at a tough decision, and your brain feels fried. What if, instead of spinning in circles, you could just talk it out with an AI partner who organizes your thoughts in minutes?</p></div><p>As leaders, we are asked to make dozens - sometimes hundreds - of decisions every week. Big or small, they all pile up. By the end of the day, we are not just tired - we are dealing with <em>decision fatigue</em>. Clarity slips, confidence wavers, and we risk defaulting to the easiest option instead of the best one.</p><p><strong>But what if you had a partner - not to decide for you, but to help you think </strong><em><strong>better</strong></em><strong>?</strong></p><p>This idea aligns perfectly with the work of <strong><a href="https://substack.com/@leadershipinchange10">Joel Salinas</a></strong>, who writes the <em><strong>Leadership in Change</strong></em> newsletter - &#8220;<em>bridging the gap between leadership and AI</em>&#8221;. Joel&#8217;s mission is to equip leaders with the <strong>frameworks, guardrails, and tools</strong> they need to thrive in an AI-driven world. If you haven&#8217;t yet, check out his newsletter here &#128071;</p><div class="embedded-publication-wrap" data-attrs="{&quot;id&quot;:4640380,&quot;name&quot;:&quot;Leadership in Change&quot;,&quot;logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!msYN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9892c1c1-6a0b-4f5c-aab9-45ad65656e64_1024x1024.png&quot;,&quot;base_url&quot;:&quot;https://leadershipinchange10.substack.com&quot;,&quot;hero_text&quot;:&quot;Lead with AI. Lead through AI. Lead despite AI. The weekly playbook for leaders who want to get it right.&quot;,&quot;author_name&quot;:&quot;Joel Salinas&quot;,&quot;show_subscribe&quot;:true,&quot;logo_bg_color&quot;:&quot;#fafafa&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="EmbeddedPublicationToDOMWithSubscribe"><div class="embedded-publication show-subscribe"><a class="embedded-publication-link-part" native="true" href="https://leadershipinchange10.substack.com?utm_source=substack&amp;utm_campaign=publication_embed&amp;utm_medium=web"><img class="embedded-publication-logo" src="https://substackcdn.com/image/fetch/$s_!msYN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9892c1c1-6a0b-4f5c-aab9-45ad65656e64_1024x1024.png" width="56" height="56" style="background-color: rgb(250, 250, 250);"><span class="embedded-publication-name">Leadership in Change</span><div class="embedded-publication-hero-text">Lead with AI. Lead through AI. Lead despite AI. The weekly playbook for leaders who want to get it right.</div><div class="embedded-publication-author-name">By Joel Salinas</div></a><form class="embedded-publication-subscribe" method="GET" action="https://leadershipinchange10.substack.com/subscribe?"><input type="hidden" name="source" value="publication-embed"><input type="hidden" name="autoSubmit" value="true"><input type="email" class="email-input" name="email" placeholder="Type your email..."><input type="submit" class="button primary" value="Subscribe"></form></div></div><div><hr></div><p>Together, we&#8217;ve built a lightweight system using <em>n8n</em><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a> that any leader can set up - no coding required!</p><h1>Here is how it works</h1><ul><li><p><strong>&#9997;&#65039; Capture your dilemma</strong> &#8594; Type or speak your decision into a chat app (<em>Telegram</em>).</p></li><li><p><strong>&#129504; Get structured feedback</strong> &#8594; An AI assistant returns a breakdown of pros, cons, risks, and next steps in minutes.</p></li><li><p><strong>&#128211; Build your decision journal</strong> &#8594; Each analysis is automatically logged (Google Sheets) so you can reflect and refine over time.</p></li></ul><p>From the user&#8217;s perspective, it works like this:</p><blockquote><p><strong>Leader (you):</strong> <em>&#8220;I&#8217;m torn. Should I promote Jane (an internal candidate) to the vacant team lead position, or hire someone from outside?&#8221;<br></em> <strong>Decision Assistant:</strong> <em>&#8220;Sure, I can help with that decision. First, can I ask: What&#8217;s your top priority in this choice - speed, cost, team morale, expertise... or something else?&#8221;<br></em> <strong>Leader:</strong> <em>&#8220;Good question. The biggest factor is speed - we need a leader ASAP to get the project back on track. Budget is also a concern; we can&#8217;t spend a fortune hiring&#8221;.<br></em> <strong>Decision Assistant:</strong> <em>&#8220;Understood. So, promoting internally might be faster and cheaper, while hiring externally might bring more experience. Let&#8217;s break it down. Here&#8217;s what I see:<br></em> <strong>- Restated Question:</strong> <em>Deciding whether to promote Jane (internal) vs. hire an external candidate for the team lead role.<br></em> - <strong>Pros of Promoting Jane:</strong> <em>She&#8217;s already familiar with the team and projects, so virtually no onboarding time. Likely boosts team morale (shows growth opportunities). Lower hiring cost and quicker fill since it&#8217;s internal.<br></em> - <strong>Cons of Promoting Jane:</strong> <em>She doesn&#8217;t have prior leadership experience; there might be a learning curve. You might still need to fill her old position. Team might perceive favoritism if others wanted the role.<br></em> - <strong>Pros of Hiring Externally:</strong> <em>Bring in a fresh perspective and possibly specific leadership experience. No internal power shifts or backfills needed.<br></em> - <strong>Cons of Hiring Externally:</strong> <em>Costlier and slower - recruiting could take 1-2 months plus onboarding. Cultural fit is unknown; there&#8217;s a risk they might not gel with the team.<br></em> - <strong>Risks &amp; Considerations:</strong> <em>If Jane is promoted without training, the project could suffer if she struggles (risk to timeline). If a new hire doesn&#8217;t work out, you lose time and money and might demoralize internal team members who wanted a promotion.<br></em> - <strong>Next Steps (if Promoting Jane):</strong> <em>Maybe set up a mentorship or training plan to support her transition. Communicate to the team why she was chosen to keep things transparent.<br></em> - <strong>Next Steps (if Hiring Externally):</strong> <em>Define the exact skill gaps you need filled (to justify the hire) and involve the team in interviews to ensure cultural fit. Consider a contract-to-hire trial if possible.<br></em> <em>Hope this helps! Remember, there&#8217;s no perfect answer, but now you have a clearer view. You&#8217;ve got this!</em>&#8221;</p></blockquote><p>Notice how the assistant kept a conversational tone - it even asked a clarifying question upfront - and then delivered the analysis in a friendly, but structured format. The leader can now review this and make a more informed decision.</p><h1>We have prepared</h1><ul><li><p>&#9881;&#65039; <strong>Ready-to-use no-code workflow</strong> you can drop straight into <em>n8n</em></p></li><li><p>&#129534; <strong>Pre-written prompt</strong> for the &#8220;<em>Decision Helper</em>&#8221; persona</p></li></ul><h1>n8n workflow template </h1><blockquote><p><em>JSON format</em></p></blockquote><p>Just copy the JSON below, drop it into <em>n8n</em>, and you are up and running in minutes.</p><pre><code>{
  &#8220;nodes&#8221;: [
    {
      &#8220;parameters&#8221;: {
        &#8220;model&#8221;: {
          &#8220;__rl&#8221;: true,
          &#8220;mode&#8221;: &#8220;list&#8221;,
          &#8220;value&#8221;: &#8220;gpt-4.1-mini&#8221;
        },
        &#8220;options&#8221;: {}
      },
      &#8220;type&#8221;: &#8220;@n8n/n8n-nodes-langchain.lmChatOpenAi&#8221;,
      &#8220;typeVersion&#8221;: 1.2,
      &#8220;position&#8221;: [
        512,
        240
      ],
      &#8220;id&#8221;: &#8220;f907379f-ef24-481b-8073-18a4dfa8dc22&#8221;,
      &#8220;name&#8221;: &#8220;OpenAI Chat Model&#8221;,
      &#8220;credentials&#8221;: {
        &#8220;openAiApi&#8221;: {
          &#8220;id&#8221;: &#8220;dT0K0OLLepjTBJZR&#8221;,
          &#8220;name&#8221;: &#8220;OpenAi account&#8221;
        }
      }
    },
    {
      &#8220;parameters&#8221;: {
        &#8220;sessionIdType&#8221;: &#8220;customKey&#8221;,
        &#8220;sessionKey&#8221;: &#8220;={{ $(&#8217;Message from Telegram&#8217;).item.json.message.from.id }}&#8221;,
        &#8220;contextWindowLength&#8221;: 50
      },
      &#8220;type&#8221;: &#8220;@n8n/n8n-nodes-langchain.memoryBufferWindow&#8221;,
      &#8220;typeVersion&#8221;: 1.3,
      &#8220;position&#8221;: [
        656,
        304
      ],
      &#8220;id&#8221;: &#8220;f356c69a-6202-4905-a2d4-6225d3039bcd&#8221;,
      &#8220;name&#8221;: &#8220;Simple Memory&#8221;
    },
    {
      &#8220;parameters&#8221;: {
        &#8220;operation&#8221;: &#8220;appendOrUpdate&#8221;,
        &#8220;documentId&#8221;: {
          &#8220;__rl&#8221;: true,
          &#8220;value&#8221;: &#8220;19x9V9aSxvqzOw7K_Jp9xVUfSuTi1gIo9IDblZRxImfw&#8221;,
          &#8220;mode&#8221;: &#8220;list&#8221;,
          &#8220;cachedResultName&#8221;: &#8220;Decisions&#8221;,
          &#8220;cachedResultUrl&#8221;: &#8220;https://docs.google.com/spreadsheets/d/19x9V9aSxvqzOw7K_Jp9xVUfSuTi1gIo9IDblZRxImfw/edit?usp=drivesdk&#8221;
        },
        &#8220;sheetName&#8221;: {
          &#8220;__rl&#8221;: true,
          &#8220;value&#8221;: &#8220;gid=0&#8221;,
          &#8220;mode&#8221;: &#8220;list&#8221;,
          &#8220;cachedResultName&#8221;: &#8220;decisions&#8221;,
          &#8220;cachedResultUrl&#8221;: &#8220;https://docs.google.com/spreadsheets/d/19x9V9aSxvqzOw7K_Jp9xVUfSuTi1gIo9IDblZRxImfw/edit#gid=0&#8221;
        },
        &#8220;columns&#8221;: {
          &#8220;mappingMode&#8221;: &#8220;defineBelow&#8221;,
          &#8220;value&#8221;: {
            &#8220;id&#8221;: &#8220;={{ /*n8n-auto-generated-fromAI-override*/ $fromAI(&#8217;id__using_to_match_&#8217;, ``, &#8216;string&#8217;) }}&#8221;,
            &#8220;question&#8221;: &#8220;={{ /*n8n-auto-generated-fromAI-override*/ $fromAI(&#8217;question&#8217;, ``, &#8216;string&#8217;) }}&#8221;,
            &#8220;pros&#8221;: &#8220;={{ /*n8n-auto-generated-fromAI-override*/ $fromAI(&#8217;pros&#8217;, ``, &#8216;string&#8217;) }}&#8221;,
            &#8220;cons&#8221;: &#8220;={{ /*n8n-auto-generated-fromAI-override*/ $fromAI(&#8217;cons&#8217;, ``, &#8216;string&#8217;) }}&#8221;,
            &#8220;risks&#8221;: &#8220;={{ /*n8n-auto-generated-fromAI-override*/ $fromAI(&#8217;risks&#8217;, ``, &#8216;string&#8217;) }}&#8221;,
            &#8220;outcome&#8221;: &#8220;={{ /*n8n-auto-generated-fromAI-override*/ $fromAI(&#8217;outcome&#8217;, ``, &#8216;string&#8217;) }}&#8221;
          },
          &#8220;matchingColumns&#8221;: [
            &#8220;id&#8221;
          ],
          &#8220;schema&#8221;: [
            {
              &#8220;id&#8221;: &#8220;id&#8221;,
              &#8220;displayName&#8221;: &#8220;id&#8221;,
              &#8220;required&#8221;: false,
              &#8220;defaultMatch&#8221;: true,
              &#8220;display&#8221;: true,
              &#8220;type&#8221;: &#8220;string&#8221;,
              &#8220;canBeUsedToMatch&#8221;: true,
              &#8220;removed&#8221;: false
            },
            {
              &#8220;id&#8221;: &#8220;question&#8221;,
              &#8220;displayName&#8221;: &#8220;question&#8221;,
              &#8220;required&#8221;: false,
              &#8220;defaultMatch&#8221;: false,
              &#8220;display&#8221;: true,
              &#8220;type&#8221;: &#8220;string&#8221;,
              &#8220;canBeUsedToMatch&#8221;: true
            },
            {
              &#8220;id&#8221;: &#8220;pros&#8221;,
              &#8220;displayName&#8221;: &#8220;pros&#8221;,
              &#8220;required&#8221;: false,
              &#8220;defaultMatch&#8221;: false,
              &#8220;display&#8221;: true,
              &#8220;type&#8221;: &#8220;string&#8221;,
              &#8220;canBeUsedToMatch&#8221;: true
            },
            {
              &#8220;id&#8221;: &#8220;cons&#8221;,
              &#8220;displayName&#8221;: &#8220;cons&#8221;,
              &#8220;required&#8221;: false,
              &#8220;defaultMatch&#8221;: false,
              &#8220;display&#8221;: true,
              &#8220;type&#8221;: &#8220;string&#8221;,
              &#8220;canBeUsedToMatch&#8221;: true
            },
            {
              &#8220;id&#8221;: &#8220;risks&#8221;,
              &#8220;displayName&#8221;: &#8220;risks&#8221;,
              &#8220;required&#8221;: false,
              &#8220;defaultMatch&#8221;: false,
              &#8220;display&#8221;: true,
              &#8220;type&#8221;: &#8220;string&#8221;,
              &#8220;canBeUsedToMatch&#8221;: true
            },
            {
              &#8220;id&#8221;: &#8220;outcome&#8221;,
              &#8220;displayName&#8221;: &#8220;outcome&#8221;,
              &#8220;required&#8221;: false,
              &#8220;defaultMatch&#8221;: false,
              &#8220;display&#8221;: true,
              &#8220;type&#8221;: &#8220;string&#8221;,
              &#8220;canBeUsedToMatch&#8221;: true
            }
          ],
          &#8220;attemptToConvertTypes&#8221;: false,
          &#8220;convertFieldsToString&#8221;: false
        },
        &#8220;options&#8221;: {}
      },
      &#8220;type&#8221;: &#8220;n8n-nodes-base.googleSheetsTool&#8221;,
      &#8220;typeVersion&#8221;: 4.7,
      &#8220;position&#8221;: [
        816,
        272
      ],
      &#8220;id&#8221;: &#8220;59182c57-90d9-447c-a02c-2135abc3cb5e&#8221;,
      &#8220;name&#8221;: &#8220;Decisions Store Sheets&#8221;,
      &#8220;credentials&#8221;: {
        &#8220;googleSheetsOAuth2Api&#8221;: {
          &#8220;id&#8221;: &#8220;xd4WsMz5QECK83x8&#8221;,
          &#8220;name&#8221;: &#8220;Google Sheets account&#8221;
        }
      }
    },
    {
      &#8220;parameters&#8221;: {
        &#8220;updates&#8221;: [
          &#8220;message&#8221;
        ],
        &#8220;additionalFields&#8221;: {}
      },
      &#8220;type&#8221;: &#8220;n8n-nodes-base.telegramTrigger&#8221;,
      &#8220;typeVersion&#8221;: 1.2,
      &#8220;position&#8221;: [
        -224,
        -16
      ],
      &#8220;id&#8221;: &#8220;53079675-5adc-493f-a743-e70717959b4e&#8221;,
      &#8220;name&#8221;: &#8220;Message from Telegram&#8221;,
      &#8220;webhookId&#8221;: &#8220;bf8b612d-f7f3-485d-bb7b-bd406e085a3e&#8221;,
      &#8220;credentials&#8221;: {
        &#8220;telegramApi&#8221;: {
          &#8220;id&#8221;: &#8220;g0ZPqCipP2D23k0A&#8221;,
          &#8220;name&#8221;: &#8220;Telegram account&#8221;
        }
      }
    },
    {
      &#8220;parameters&#8221;: {
        &#8220;rules&#8221;: {
          &#8220;values&#8221;: [
            {
              &#8220;conditions&#8221;: {
                &#8220;options&#8221;: {
                  &#8220;caseSensitive&#8221;: true,
                  &#8220;leftValue&#8221;: &#8220;&#8221;,
                  &#8220;typeValidation&#8221;: &#8220;strict&#8221;,
                  &#8220;version&#8221;: 2
                },
                &#8220;conditions&#8221;: [
                  {
                    &#8220;leftValue&#8221;: &#8220;={{ $json.message.voice }}&#8221;,
                    &#8220;rightValue&#8221;: &#8220;&#8221;,
                    &#8220;operator&#8221;: {
                      &#8220;type&#8221;: &#8220;object&#8221;,
                      &#8220;operation&#8221;: &#8220;exists&#8221;,
                      &#8220;singleValue&#8221;: true
                    },
                    &#8220;id&#8221;: &#8220;ddba36ab-d86e-48b9-a07a-ecfeccab6cf0&#8221;
                  }
                ],
                &#8220;combinator&#8221;: &#8220;and&#8221;
              },
              &#8220;renameOutput&#8221;: true,
              &#8220;outputKey&#8221;: &#8220;voice&#8221;
            },
            {
              &#8220;conditions&#8221;: {
                &#8220;options&#8221;: {
                  &#8220;caseSensitive&#8221;: true,
                  &#8220;leftValue&#8221;: &#8220;&#8221;,
                  &#8220;typeValidation&#8221;: &#8220;strict&#8221;,
                  &#8220;version&#8221;: 2
                },
                &#8220;conditions&#8221;: [
                  {
                    &#8220;id&#8221;: &#8220;1da461c3-a8ac-4abd-a3b6-3a9f84b94823&#8221;,
                    &#8220;leftValue&#8221;: &#8220;={{ $json.message.text }}&#8221;,
                    &#8220;rightValue&#8221;: &#8220;&#8221;,
                    &#8220;operator&#8221;: {
                      &#8220;type&#8221;: &#8220;string&#8221;,
                      &#8220;operation&#8221;: &#8220;exists&#8221;,
                      &#8220;singleValue&#8221;: true
                    }
                  }
                ],
                &#8220;combinator&#8221;: &#8220;and&#8221;
              },
              &#8220;renameOutput&#8221;: true,
              &#8220;outputKey&#8221;: &#8220;text&#8221;
            }
          ]
        },
        &#8220;options&#8221;: {}
      },
      &#8220;type&#8221;: &#8220;n8n-nodes-base.switch&#8221;,
      &#8220;typeVersion&#8221;: 3.2,
      &#8220;position&#8221;: [
        -16,
        -16
      ],
      &#8220;id&#8221;: &#8220;64576c37-1bc7-49ce-9718-5a15bc08f2d1&#8221;,
      &#8220;name&#8221;: &#8220;Voice or text?&#8221;
    },
    {
      &#8220;parameters&#8221;: {
        &#8220;resource&#8221;: &#8220;file&#8221;,
        &#8220;fileId&#8221;: &#8220;={{ $json.message.voice.file_id }}&#8221;,
        &#8220;additionalFields&#8221;: {}
      },
      &#8220;type&#8221;: &#8220;n8n-nodes-base.telegram&#8221;,
      &#8220;typeVersion&#8221;: 1.2,
      &#8220;position&#8221;: [
        240,
        -160
      ],
      &#8220;id&#8221;: &#8220;06fc0767-1566-44dd-9390-63b02af392da&#8221;,
      &#8220;name&#8221;: &#8220;Get a file with voice message&#8221;,
      &#8220;webhookId&#8221;: &#8220;5118af6c-a794-4cfa-ab94-97f4e1eb9854&#8221;,
      &#8220;credentials&#8221;: {
        &#8220;telegramApi&#8221;: {
          &#8220;id&#8221;: &#8220;g0ZPqCipP2D23k0A&#8221;,
          &#8220;name&#8221;: &#8220;Telegram account&#8221;
        }
      }
    },
    {
      &#8220;parameters&#8221;: {
        &#8220;resource&#8221;: &#8220;audio&#8221;,
        &#8220;operation&#8221;: &#8220;transcribe&#8221;,
        &#8220;options&#8221;: {}
      },
      &#8220;type&#8221;: &#8220;@n8n/n8n-nodes-langchain.openAi&#8221;,
      &#8220;typeVersion&#8221;: 1.8,
      &#8220;position&#8221;: [
        400,
        -160
      ],
      &#8220;id&#8221;: &#8220;55630e67-9caf-4002-b5af-bb1ddaa73122&#8221;,
      &#8220;name&#8221;: &#8220;Transcribe voice message into text&#8221;,
      &#8220;credentials&#8221;: {
        &#8220;openAiApi&#8221;: {
          &#8220;id&#8221;: &#8220;dT0K0OLLepjTBJZR&#8221;,
          &#8220;name&#8221;: &#8220;OpenAi account&#8221;
        }
      }
    },
    {
      &#8220;parameters&#8221;: {
        &#8220;promptType&#8221;: &#8220;define&#8221;,
        &#8220;text&#8221;: &#8220;=You are \&#8221;Decision Helper\&#8221;, a conversational agent for leaders.\nYou guide them through decisions in a simple, structured way.\nYou speak plainly, ask one question at a time, and present your analysis in clean structured text.\nYou support a non-technical audience.\n\n==================================================\nGOALS\n1) Understand the decision via 3 sequential follow-up questions (ask ONE at a time).\n2) Consider prior, similar decisions and outcomes (these may be provided in the context).\n3) Provide analysis: exactly 3 pros, 3 cons, 3 risks, and 3 alternative next steps.\n4) Present the analysis in structured plain text that is easy to read.\n5) When the leader later decides on a next step and shares the outcome,  pass the summary and the outcome to the tool `Decisions Store Sheets`.\n6) If the leader interrupts and wants to start a new decision, you must immediately reset and begin Phase A fresh with the new decision text. Ignore previous answers once reset.\n\n==================================================\nCONVERSATION FLOW\nPHASE A &#8212; FOLLOW-UPS\n- Ask exactly 3 follow-up questions, ONE at a time.\n- After each question, wait for the leader&#8217;s answer before continuing.\n- Only proceed to PHASE B after all 3 answers are captured.\n\nPHASE B &#8212; ANALYSIS\n- Use the decision text + the 3 answers + any prior decisions provided.\n- Produce exactly:\n  - **Pros:** 3 short bullet points\n  - **Cons:** 3 short bullet points\n  - **Risks:** 3 short bullet points\n  - **Next Steps:** 3 alternatives, each with: label, rationale, and first step\n- If relevant, briefly reference one insight from similar prior decisions.\n- Present this as structured plain text, not JSON.\n\nPHASE C &#8212; OUTCOME LOGGING\n- When the leader confirms their chosen option or reports results, call the tool `Decisions Store Sheets` with the outcome formatted as JSON, details:\n  - selected option label\n  - rationale (if given)\n  - result (e.g., approved, postponed, rejected, succeeded, failed, mixed)\n  - notes (if given)\n\n==================================================\nSTYLE &amp; CONSTRAINTS\n- Audience: non-technical leaders. Use short, clear, practical language.\n- Lists: exactly 3 items per category.\n- Do not output JSON, code fences, or markdown beyond basic bold and bullets.\n- If a decision seems unsafe/illegal, ask a clarifying follow-up before analysis.\n\n==================================================\nJSON formatted data for `Decisions Store Sheets`\n\n{\n  \&#8221;type\&#8221;: \&#8221;object\&#8221;,\n  \&#8221;properties\&#8221;: {\n    \&#8221;timestamp\&#8221;: {\n      \&#8221;type\&#8221;: \&#8221;string\&#8221;,\n      \&#8221;format\&#8221;: \&#8221;date-time\&#8221;,\n      \&#8221;description\&#8221;: \&#8221;ISO8601 timestamp when the decision was logged\&#8221;\n    },\n    \&#8221;decision_text\&#8221;: {\n      \&#8221;type\&#8221;: \&#8221;string\&#8221;,\n      \&#8221;description\&#8221;: \&#8221;Original decision statement provided by the leader\&#8221;\n    },\n    \&#8221;answers_q1\&#8221;: {\n      \&#8221;type\&#8221;: \&#8221;string\&#8221;,\n      \&#8221;description\&#8221;: \&#8221;Answer to follow-up question 1\&#8221;\n    },\n    \&#8221;answers_q2\&#8221;: {\n      \&#8221;type\&#8221;: \&#8221;string\&#8221;,\n      \&#8221;description\&#8221;: \&#8221;Answer to follow-up question 2\&#8221;\n    },\n    \&#8221;answers_q3\&#8221;: {\n      \&#8221;type\&#8221;: \&#8221;string\&#8221;,\n      \&#8221;description\&#8221;: \&#8221;Answer to follow-up question 3\&#8221;\n    },\n    \&#8221;pros\&#8221;: {\n      \&#8221;type\&#8221;: \&#8221;string\&#8221;,\n      \&#8221;description\&#8221;: \&#8221;Concatenated pros, separated by bullet or semicolon\&#8221;\n    },\n    \&#8221;cons\&#8221;: {\n      \&#8221;type\&#8221;: \&#8221;string\&#8221;,\n      \&#8221;description\&#8221;: \&#8221;Concatenated cons, separated by bullet or semicolon\&#8221;\n    },\n    \&#8221;risks\&#8221;: {\n      \&#8221;type\&#8221;: \&#8221;string\&#8221;,\n      \&#8221;description\&#8221;: \&#8221;Concatenated risks, separated by bullet or semicolon\&#8221;\n    },\n    \&#8221;next_steps\&#8221;: {\n      \&#8221;type\&#8221;: \&#8221;string\&#8221;,\n      \&#8221;description\&#8221;: \&#8221;Concatenated next steps, e.g. &#8216;A) label - rationale - first step | B)... | C)...&#8217;\&#8221;\n    },\n    \&#8221;outcome\&#8221;: {\n      \&#8221;type\&#8221;: \&#8221;string\&#8221;,\n      \&#8221;description\&#8221;: \&#8221;Final chosen outcome or decision result\&#8221;\n    }\n  },\n  \&#8221;required\&#8221;: [\n    \&#8221;type\&#8221;,\n    \&#8221;timestamp\&#8221;,\n    \&#8221;decision_text\&#8221;,\n    \&#8221;answers_q1\&#8221;,\n    \&#8221;answers_q2\&#8221;,\n    \&#8221;answers_q3\&#8221;,\n    \&#8221;pros\&#8221;,\n    \&#8221;cons\&#8221;,\n    \&#8221;risks\&#8221;,\n    \&#8221;next_steps\&#8221;,\n    \&#8221;outcome\&#8221;\n  ]\n}\n\n\n==================================================\nUSER INPUT:\n{{ $json.text }}\n{{ $json.message.text }}&#8221;,
        &#8220;options&#8221;: {
          &#8220;systemMessage&#8221;: &#8220;=Today is {{ Date.now() }}.&#8221;,
          &#8220;returnIntermediateSteps&#8221;: false
        }
      },
      &#8220;type&#8221;: &#8220;@n8n/n8n-nodes-langchain.agent&#8221;,
      &#8220;typeVersion&#8221;: 2.2,
      &#8220;position&#8221;: [
        624,
        0
      ],
      &#8220;id&#8221;: &#8220;91252a7c-e566-4920-ab0e-3ebd8e9367c3&#8221;,
      &#8220;name&#8221;: &#8220;Decision Assistant Agent&#8221;
    },
    {
      &#8220;parameters&#8221;: {
        &#8220;chatId&#8221;: &#8220;={{ $(&#8217;Message from Telegram&#8217;).item.json.message.from.id }}&#8221;,
        &#8220;text&#8221;: &#8220;={{ $json.output }}&#8221;,
        &#8220;additionalFields&#8221;: {}
      },
      &#8220;type&#8221;: &#8220;n8n-nodes-base.telegram&#8221;,
      &#8220;typeVersion&#8221;: 1.2,
      &#8220;position&#8221;: [
        976,
        0
      ],
      &#8220;id&#8221;: &#8220;0ae7dad8-7fac-4dce-9ace-9e8027f293ec&#8221;,
      &#8220;name&#8221;: &#8220;Telegram an agent response message&#8221;,
      &#8220;webhookId&#8221;: &#8220;9cd6cf1c-e995-47aa-a074-5f10e5bfa163&#8221;,
      &#8220;credentials&#8221;: {
        &#8220;telegramApi&#8221;: {
          &#8220;id&#8221;: &#8220;g0ZPqCipP2D23k0A&#8221;,
          &#8220;name&#8221;: &#8220;Telegram account&#8221;
        }
      }
    }
  ],
  &#8220;connections&#8221;: {
    &#8220;OpenAI Chat Model&#8221;: {
      &#8220;ai_languageModel&#8221;: [
        [
          {
            &#8220;node&#8221;: &#8220;Decision Assistant Agent&#8221;,
            &#8220;type&#8221;: &#8220;ai_languageModel&#8221;,
            &#8220;index&#8221;: 0
          }
        ]
      ]
    },
    &#8220;Simple Memory&#8221;: {
      &#8220;ai_memory&#8221;: [
        [
          {
            &#8220;node&#8221;: &#8220;Decision Assistant Agent&#8221;,
            &#8220;type&#8221;: &#8220;ai_memory&#8221;,
            &#8220;index&#8221;: 0
          }
        ]
      ]
    },
    &#8220;Decisions Store Sheets&#8221;: {
      &#8220;ai_tool&#8221;: [
        [
          {
            &#8220;node&#8221;: &#8220;Decision Assistant Agent&#8221;,
            &#8220;type&#8221;: &#8220;ai_tool&#8221;,
            &#8220;index&#8221;: 0
          }
        ]
      ]
    },
    &#8220;Message from Telegram&#8221;: {
      &#8220;main&#8221;: [
        [
          {
            &#8220;node&#8221;: &#8220;Voice or text?&#8221;,
            &#8220;type&#8221;: &#8220;main&#8221;,
            &#8220;index&#8221;: 0
          }
        ]
      ]
    },
    &#8220;Voice or text?&#8221;: {
      &#8220;main&#8221;: [
        [
          {
            &#8220;node&#8221;: &#8220;Get a file with voice message&#8221;,
            &#8220;type&#8221;: &#8220;main&#8221;,
            &#8220;index&#8221;: 0
          }
        ],
        [
          {
            &#8220;node&#8221;: &#8220;Decision Assistant Agent&#8221;,
            &#8220;type&#8221;: &#8220;main&#8221;,
            &#8220;index&#8221;: 0
          }
        ]
      ]
    },
    &#8220;Get a file with voice message&#8221;: {
      &#8220;main&#8221;: [
        [
          {
            &#8220;node&#8221;: &#8220;Transcribe voice message into text&#8221;,
            &#8220;type&#8221;: &#8220;main&#8221;,
            &#8220;index&#8221;: 0
          }
        ]
      ]
    },
    &#8220;Transcribe voice message into text&#8221;: {
      &#8220;main&#8221;: [
        [
          {
            &#8220;node&#8221;: &#8220;Decision Assistant Agent&#8221;,
            &#8220;type&#8221;: &#8220;main&#8221;,
            &#8220;index&#8221;: 0
          }
        ]
      ]
    },
    &#8220;Decision Assistant Agent&#8221;: {
      &#8220;main&#8221;: [
        [
          {
            &#8220;node&#8221;: &#8220;Telegram an agent response message&#8221;,
            &#8220;type&#8221;: &#8220;main&#8221;,
            &#8220;index&#8221;: 0
          }
        ]
      ]
    }
  },
  &#8220;pinData&#8221;: {},
  &#8220;meta&#8221;: {
    &#8220;templateCredsSetupCompleted&#8221;: true,
    &#8220;instanceId&#8221;: &#8220;992ac2542863ba689f62908163525ecb734f9f80532de01b501f2657b08b56c0&#8221;
  }
}</code></pre><h1>The prompt for AI agent</h1><pre><code>You are &#8220;Decision Helper&#8221;, a conversational agent for leaders.
You guide them through decisions in a simple, structured way.
You speak plainly, ask one question at a time, and present your analysis in clean structured text.
You support a non-technical audience.

==================================================
GOALS
1) Understand the decision via 3 sequential follow-up questions (ask ONE at a time).
2) Consider prior, similar decisions and outcomes (these may be provided in the context).
3) Provide analysis: exactly 3 pros, 3 cons, 3 risks, and 3 alternative next steps.
4) Present the analysis in structured plain text that is easy to read.
5) When the leader later decides on a next step and shares the outcome,  pass the summary and the outcome to the tool `Decisions Store Sheets`.
6) If the leader interrupts and wants to start a new decision, you must immediately reset and begin Phase A fresh with the new decision text. Ignore previous answers once reset.

==================================================
CONVERSATION FLOW
PHASE A &#8212; FOLLOW-UPS
- Ask exactly 3 follow-up questions, ONE at a time.
- After each question, wait for the leader&#8217;s answer before continuing.
- Only proceed to PHASE B after all 3 answers are captured.

PHASE B &#8212; ANALYSIS
- Use the decision text + the 3 answers + any prior decisions provided.
- Produce exactly:
  - **Pros:** 3 short bullet points
  - **Cons:** 3 short bullet points
  - **Risks:** 3 short bullet points
  - **Next Steps:** 3 alternatives, each with: label, rationale, and first step
- If relevant, briefly reference one insight from similar prior decisions.
- Present this as structured plain text, not JSON.

PHASE C &#8212; OUTCOME LOGGING
- When the leader confirms their chosen option or reports results, call the tool `Decisions Store Sheets` with the outcome formatted as JSON, details:
  - selected option label
  - rationale (if given)
  - result (e.g., approved, postponed, rejected, succeeded, failed, mixed)
  - notes (if given)

==================================================
STYLE &amp; CONSTRAINTS
- Audience: non-technical leaders. Use short, clear, practical language.
- Lists: exactly 3 items per category.
- Do not output JSON, code fences, or markdown beyond basic bold and bullets.
- If a decision seems unsafe/illegal, ask a clarifying follow-up before analysis.

==================================================
JSON formatted data for `Decisions Store Sheets`

{
  &#8220;type&#8221;: &#8220;object&#8221;,
  &#8220;properties&#8221;: {
    &#8220;timestamp&#8221;: {
      &#8220;type&#8221;: &#8220;string&#8221;,
      &#8220;format&#8221;: &#8220;date-time&#8221;,
      &#8220;description&#8221;: &#8220;ISO8601 timestamp when the decision was logged&#8221;
    },
    &#8220;decision_text&#8221;: {
      &#8220;type&#8221;: &#8220;string&#8221;,
      &#8220;description&#8221;: &#8220;Original decision statement provided by the leader&#8221;
    },
    &#8220;answers_q1&#8221;: {
      &#8220;type&#8221;: &#8220;string&#8221;,
      &#8220;description&#8221;: &#8220;Answer to follow-up question 1&#8221;
    },
    &#8220;answers_q2&#8221;: {
      &#8220;type&#8221;: &#8220;string&#8221;,
      &#8220;description&#8221;: &#8220;Answer to follow-up question 2&#8221;
    },
    &#8220;answers_q3&#8221;: {
      &#8220;type&#8221;: &#8220;string&#8221;,
      &#8220;description&#8221;: &#8220;Answer to follow-up question 3&#8221;
    },
    &#8220;pros&#8221;: {
      &#8220;type&#8221;: &#8220;string&#8221;,
      &#8220;description&#8221;: &#8220;Concatenated pros, separated by bullet or semicolon&#8221;
    },
    &#8220;cons&#8221;: {
      &#8220;type&#8221;: &#8220;string&#8221;,
      &#8220;description&#8221;: &#8220;Concatenated cons, separated by bullet or semicolon&#8221;
    },
    &#8220;risks&#8221;: {
      &#8220;type&#8221;: &#8220;string&#8221;,
      &#8220;description&#8221;: &#8220;Concatenated risks, separated by bullet or semicolon&#8221;
    },
    &#8220;next_steps&#8221;: {
      &#8220;type&#8221;: &#8220;string&#8221;,
      &#8220;description&#8221;: &#8220;Concatenated next steps, e.g. &#8216;A) label - rationale - first step | B)... | C)...&#8217;&#8221;
    },
    &#8220;outcome&#8221;: {
      &#8220;type&#8221;: &#8220;string&#8221;,
      &#8220;description&#8221;: &#8220;Final chosen outcome or decision result&#8221;
    }
  },
  &#8220;required&#8221;: [
    &#8220;type&#8221;,
    &#8220;timestamp&#8221;,
    &#8220;decision_text&#8221;,
    &#8220;answers_q1&#8221;,
    &#8220;answers_q2&#8221;,
    &#8220;answers_q3&#8221;,
    &#8220;pros&#8221;,
    &#8220;cons&#8221;,
    &#8220;risks&#8221;,
    &#8220;next_steps&#8221;,
    &#8220;outcome&#8221;
  ]
}


==================================================
USER INPUT:
{{ $json.text }}
{{ $json.message.text }}</code></pre><p>This is just the surface. </p><p>We&#8217;ll share the full <strong>technical walk-through</strong> - complete with workflows, API setups, and system configurations - in <em>&#8220;Late-night decisions, meet your AI thinking partner: a leader&#8217;s story (Part 2)&#8221;</em>.</p><div><hr></div><p><strong>&#129504; Curious about automation, workflows, n8n, AI, or AI agents?</strong></p><p>If you&#8217;re exploring how all these tools connect - and how to actually build with them - you&#8217;re in the right place.</p><p><strong>&#128236; Subscribe to get more deep dives, tools, experiments, and real-world workflows delivered straight to you.</strong></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><p>If Joel&#8217;s <em>Leadership in Change</em> is about <strong>frameworks and guardrails</strong>, this series shows how to put them into practice with accessible AI tools. </p><p><strong>The future of leadership isn&#8217;t man vs. machine - it&#8217;s partnership!</strong></p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p><a href="https://n8n.io/">n8n: Flexible AI workflow automation for technical teams</a></p></div></div>]]></content:encoded></item><item><title><![CDATA[Supercharge your Substack: Build a personalized AI assistant in a few clicks 🚀🤖]]></title><description><![CDATA[Turn your latest posts and notes into new ideas with an AI sidekick powered by n8n and ChatGPT]]></description><link>https://iam.slys.dev/p/supercharge-your-substack-build-a</link><guid isPermaLink="false">https://iam.slys.dev/p/supercharge-your-substack-build-a</guid><dc:creator><![CDATA[Jakub Slys 🤖]]></dc:creator><pubDate>Wed, 24 Sep 2025 18:58:35 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!yOJs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde324198-6417-4837-849f-3d93c0555724_1536x1024.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_!yOJs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde324198-6417-4837-849f-3d93c0555724_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!yOJs!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde324198-6417-4837-849f-3d93c0555724_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!yOJs!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde324198-6417-4837-849f-3d93c0555724_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!yOJs!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde324198-6417-4837-849f-3d93c0555724_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!yOJs!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde324198-6417-4837-849f-3d93c0555724_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!yOJs!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde324198-6417-4837-849f-3d93c0555724_1536x1024.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/de324198-6417-4837-849f-3d93c0555724_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2276599,&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://iam.slys.dev/i/174357207?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde324198-6417-4837-849f-3d93c0555724_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!yOJs!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde324198-6417-4837-849f-3d93c0555724_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!yOJs!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde324198-6417-4837-849f-3d93c0555724_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!yOJs!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde324198-6417-4837-849f-3d93c0555724_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!yOJs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde324198-6417-4837-849f-3d93c0555724_1536x1024.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 role="img" 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><title></title><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>I&#8217;ve always loved writing &#128218;, but lately I was drowning in ideas and struggling to organize my newsletter content. I was reading about <em>n8n&#8217;s<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></em> AI capabilities and realized I could automate some of my workflow. <em>n8n</em> even has a <em><strong>Telegram</strong><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a></em><strong> AI bot template</strong><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a> where a <em>LangChain</em> agent talks to <em>GPT-4</em>. Inspired by that, I decided to <strong>build a </strong><em><strong>Telegram</strong></em><strong> bot assistant</strong> that pulls in my <em>Substack</em> newsletter posts and helps me brainstorm new ideas.</p><p>In the beginning, I was just a busy writer turned no-code tinkerer. I set up a <em>Telegram</em> bot (via <em>BotFather</em><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a>) to send messages to my phone, and got to work wiring up an <em>n8n</em> workflow. It felt amazing to empower myself with code &#8211; <strong>I mean no-code!</strong> &#8211; to solve my own problem. Peek at this. &#128064;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-HUb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2342e7bd-d945-418f-a8e3-ae6234402dd0_414x731.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-HUb!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2342e7bd-d945-418f-a8e3-ae6234402dd0_414x731.jpeg 424w, https://substackcdn.com/image/fetch/$s_!-HUb!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2342e7bd-d945-418f-a8e3-ae6234402dd0_414x731.jpeg 848w, https://substackcdn.com/image/fetch/$s_!-HUb!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2342e7bd-d945-418f-a8e3-ae6234402dd0_414x731.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!-HUb!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2342e7bd-d945-418f-a8e3-ae6234402dd0_414x731.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-HUb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2342e7bd-d945-418f-a8e3-ae6234402dd0_414x731.jpeg" width="414" height="731" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2342e7bd-d945-418f-a8e3-ae6234402dd0_414x731.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:731,&quot;width&quot;:414,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:45684,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/174357207?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2342e7bd-d945-418f-a8e3-ae6234402dd0_414x731.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-HUb!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2342e7bd-d945-418f-a8e3-ae6234402dd0_414x731.jpeg 424w, https://substackcdn.com/image/fetch/$s_!-HUb!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2342e7bd-d945-418f-a8e3-ae6234402dd0_414x731.jpeg 848w, https://substackcdn.com/image/fetch/$s_!-HUb!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2342e7bd-d945-418f-a8e3-ae6234402dd0_414x731.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!-HUb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2342e7bd-d945-418f-a8e3-ae6234402dd0_414x731.jpeg 1456w" sizes="100vw"></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 role="img" 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><title></title><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>Now I have a helper that listens on <em>Telegram</em>, reads my recent <em>Substack</em> notes and posts, summarizes them, and even helps me come up with newsletter ideas. It&#8217;s like having a &#129302; editor-in-chief who knows all my content.</p><div><hr></div><p>&#128640; Like where this is going? <strong>Subscribe </strong>today and <strong>join</strong> a growing community of creators experimenting with AI workflows. You&#8217;ll get step-by-step guides, real examples, and fresh ideas delivered straight to your inbox.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h1>&#128640;&#128736;&#65039; <strong>What the AI assistant can do</strong></h1><p>Here&#8217;s a quick overview of what my Telegram AI assistant can do.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Hr7K!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05b35e2d-b373-4f74-a582-6e81c03b246e_1466x620.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Hr7K!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05b35e2d-b373-4f74-a582-6e81c03b246e_1466x620.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Hr7K!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05b35e2d-b373-4f74-a582-6e81c03b246e_1466x620.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Hr7K!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05b35e2d-b373-4f74-a582-6e81c03b246e_1466x620.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Hr7K!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05b35e2d-b373-4f74-a582-6e81c03b246e_1466x620.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Hr7K!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05b35e2d-b373-4f74-a582-6e81c03b246e_1466x620.jpeg" width="1200" height="507.50341064120056" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/05b35e2d-b373-4f74-a582-6e81c03b246e_1466x620.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:620,&quot;width&quot;:1466,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:235983,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/174357207?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb6cc0400-8e84-44e7-8625-90ba02b10d69_1466x753.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Hr7K!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05b35e2d-b373-4f74-a582-6e81c03b246e_1466x620.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Hr7K!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05b35e2d-b373-4f74-a582-6e81c03b246e_1466x620.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Hr7K!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05b35e2d-b373-4f74-a582-6e81c03b246e_1466x620.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Hr7K!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05b35e2d-b373-4f74-a582-6e81c03b246e_1466x620.jpeg 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 role="img" 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><title></title><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>Chat on Telegram.</strong> It listens for any message I send on <em>Telegram</em> and responds in a friendly chat. Behind the scenes it uses <em><strong>OpenAI&#8217;s GPT-4.1</strong></em><strong> model</strong><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a> to generate its replies. Because <em>GPT-4.1</em> is optimized for instruction-following and has a huge context window, it can handle pretty complex prompts.</p><p><strong>Fetch Substack Content.</strong> It can pull in my latest <em>Substack</em> notes or posts<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-6" href="#footnote-6" target="_self">6</a>. In practice, this means I can ask the bot things like &#8220;<em>What were my last 3 notes about?</em>&#8221; or &#8220;<em>Show me a summary of the last post.</em>&#8221; and it will fetch that content for reference.</p><p><strong>Summarize and Brainstorm.</strong> The agent can summarize a full post when asked for, or brainstorm new content. I prompt it with something like &#8220;<em>Summarize my last newsletter</em>&#8221; or &#8220;<em>Brainstorm 5 ideas based on these notes</em>&#8221;, and <em>GPT-4.1</em> generates helpful suggestions. Thanks to the model&#8217;s 1-million-token context window, it can &#8220;<em>read</em>&#8221; entire articles or notes I give it. It&#8217;s also trained to follow instructions, so it knows to output a structured summary or list of ideas.</p><p><strong>Remember Chat History.</strong> It keeps track of our conversation context using a simple buffer memory. In <em>n8n</em> I attached a <em>Simple Memory</em> to the agent, which &#8220;<em>stores the entire conversation history</em>&#8221;. This means the bot can recall what we talked about earlier in the chat, so brainstorming is more coherent (it knows what we discussed last week, for example).</p><p>By combining <em>GPT-4.1</em> with these tools, my assistant can chat with me, look up my own content from <em>Substack</em>, and help turn my notes into new ideas. It&#8217;s a handy creative partner that keeps me on track with my newsletter.</p><div><hr></div><p><strong>&#128161; </strong>I&#8217;ve shown you what my AI assistant can do - but what about yours? Imagine building your own version: what features would you add, or what problems would you solve first? <strong>Share your thoughts in the comments</strong>, I&#8217;d love to exchange ideas with you.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/supercharge-your-substack-build-a/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/supercharge-your-substack-build-a/comments"><span>Leave a comment</span></a></p><div><hr></div><h1>&#128450;&#65039;&#128260; <strong>How the workflow works</strong></h1><p>The <em>n8n</em> workflow is a chain of connected nodes, each doing one step. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3zB0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f208f11-e82a-4430-a6ea-c9c6be5c0baf_2732x1717.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3zB0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f208f11-e82a-4430-a6ea-c9c6be5c0baf_2732x1717.jpeg 424w, https://substackcdn.com/image/fetch/$s_!3zB0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f208f11-e82a-4430-a6ea-c9c6be5c0baf_2732x1717.jpeg 848w, https://substackcdn.com/image/fetch/$s_!3zB0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f208f11-e82a-4430-a6ea-c9c6be5c0baf_2732x1717.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!3zB0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f208f11-e82a-4430-a6ea-c9c6be5c0baf_2732x1717.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3zB0!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f208f11-e82a-4430-a6ea-c9c6be5c0baf_2732x1717.jpeg" width="1200" height="754.1208791208791" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8f208f11-e82a-4430-a6ea-c9c6be5c0baf_2732x1717.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:915,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:409412,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/174357207?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f208f11-e82a-4430-a6ea-c9c6be5c0baf_2732x1717.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!3zB0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f208f11-e82a-4430-a6ea-c9c6be5c0baf_2732x1717.jpeg 424w, https://substackcdn.com/image/fetch/$s_!3zB0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f208f11-e82a-4430-a6ea-c9c6be5c0baf_2732x1717.jpeg 848w, https://substackcdn.com/image/fetch/$s_!3zB0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f208f11-e82a-4430-a6ea-c9c6be5c0baf_2732x1717.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!3zB0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f208f11-e82a-4430-a6ea-c9c6be5c0baf_2732x1717.jpeg 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 role="img" 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><title></title><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>Here&#8217;s a friendly walk-through of each part.</p><h2>&#128172;&#128242; <strong>Telegram Trigger node</strong></h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-kgq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa904b3a8-dd5e-41bf-89e4-2aa79af91639_467x382.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-kgq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa904b3a8-dd5e-41bf-89e4-2aa79af91639_467x382.jpeg 424w, https://substackcdn.com/image/fetch/$s_!-kgq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa904b3a8-dd5e-41bf-89e4-2aa79af91639_467x382.jpeg 848w, https://substackcdn.com/image/fetch/$s_!-kgq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa904b3a8-dd5e-41bf-89e4-2aa79af91639_467x382.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!-kgq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa904b3a8-dd5e-41bf-89e4-2aa79af91639_467x382.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-kgq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa904b3a8-dd5e-41bf-89e4-2aa79af91639_467x382.jpeg" width="467" height="382" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a904b3a8-dd5e-41bf-89e4-2aa79af91639_467x382.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:382,&quot;width&quot;:467,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:22026,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/174357207?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa904b3a8-dd5e-41bf-89e4-2aa79af91639_467x382.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-kgq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa904b3a8-dd5e-41bf-89e4-2aa79af91639_467x382.jpeg 424w, https://substackcdn.com/image/fetch/$s_!-kgq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa904b3a8-dd5e-41bf-89e4-2aa79af91639_467x382.jpeg 848w, https://substackcdn.com/image/fetch/$s_!-kgq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa904b3a8-dd5e-41bf-89e4-2aa79af91639_467x382.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!-kgq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa904b3a8-dd5e-41bf-89e4-2aa79af91639_467x382.jpeg 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 role="img" 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><title></title><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>The <em>Telegram Trigger</em> node is where it all starts. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!leNI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa951be8b-1d3a-4c43-9828-74582adfac98_832x1055.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!leNI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa951be8b-1d3a-4c43-9828-74582adfac98_832x1055.jpeg 424w, https://substackcdn.com/image/fetch/$s_!leNI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa951be8b-1d3a-4c43-9828-74582adfac98_832x1055.jpeg 848w, https://substackcdn.com/image/fetch/$s_!leNI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa951be8b-1d3a-4c43-9828-74582adfac98_832x1055.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!leNI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa951be8b-1d3a-4c43-9828-74582adfac98_832x1055.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!leNI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa951be8b-1d3a-4c43-9828-74582adfac98_832x1055.jpeg" width="832" height="1055" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a951be8b-1d3a-4c43-9828-74582adfac98_832x1055.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1055,&quot;width&quot;:832,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:122085,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/174357207?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa951be8b-1d3a-4c43-9828-74582adfac98_832x1055.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!leNI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa951be8b-1d3a-4c43-9828-74582adfac98_832x1055.jpeg 424w, https://substackcdn.com/image/fetch/$s_!leNI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa951be8b-1d3a-4c43-9828-74582adfac98_832x1055.jpeg 848w, https://substackcdn.com/image/fetch/$s_!leNI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa951be8b-1d3a-4c43-9828-74582adfac98_832x1055.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!leNI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa951be8b-1d3a-4c43-9828-74582adfac98_832x1055.jpeg 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 role="img" 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><title></title><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>I connected this node to my <em>Telegram</em> Bot&#8217;s credentials. Whenever I send a message to the bot, this trigger fires and passes the chat message text to the next node. </p><p>Essentially, it says &#8220;<em>New input from Telegram: here is the user&#8217;s message</em>&#8221;, so the workflow knows to react.</p><div><hr></div><p><strong>&#128242; Pretty cool, right?</strong> If you know someone who&#8217;s struggling with content overload or could use a little AI boost in their daily workflow, <strong>share this post with them</strong>. It might be exactly the inspiration they need to start building their own assistant.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/supercharge-your-substack-build-a?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/supercharge-your-substack-build-a?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h2>&#129504;&#129302; <strong>AI Agent node</strong></h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nAdZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d0dce99-0252-4618-b902-dba368557c90_614x396.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nAdZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d0dce99-0252-4618-b902-dba368557c90_614x396.jpeg 424w, https://substackcdn.com/image/fetch/$s_!nAdZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d0dce99-0252-4618-b902-dba368557c90_614x396.jpeg 848w, https://substackcdn.com/image/fetch/$s_!nAdZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d0dce99-0252-4618-b902-dba368557c90_614x396.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!nAdZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d0dce99-0252-4618-b902-dba368557c90_614x396.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nAdZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d0dce99-0252-4618-b902-dba368557c90_614x396.jpeg" width="614" height="396" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7d0dce99-0252-4618-b902-dba368557c90_614x396.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:396,&quot;width&quot;:614,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:31508,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/174357207?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d0dce99-0252-4618-b902-dba368557c90_614x396.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!nAdZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d0dce99-0252-4618-b902-dba368557c90_614x396.jpeg 424w, https://substackcdn.com/image/fetch/$s_!nAdZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d0dce99-0252-4618-b902-dba368557c90_614x396.jpeg 848w, https://substackcdn.com/image/fetch/$s_!nAdZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d0dce99-0252-4618-b902-dba368557c90_614x396.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!nAdZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d0dce99-0252-4618-b902-dba368557c90_614x396.jpeg 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 role="img" 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><title></title><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>Next is the <em>AI Agent</em> node. I set it up as a conversation agent with a custom system prompt that tells it to focus on content brainstorming. Here is the system prompt I have provided.</p><pre><code>You are a helpful personal assistant focused on content creation.
Your role is to help brainstorm new ideas for upcoming newsletters by reviewing and drawing inspiration from recently published content.
You can use the following tools:
* `Get recent notes`: Fetch the user&#8217;s latest notes (default: last 15).
* `Get recent posts previews`: Retrieve previews of the most recent posts, including their IDs. You use those IDs to fetch complete content of a post if needed.
* `Get full post by ID`: Fetch the complete content of a specific post, given its ID. You obtain an ID from post preview if needed.

Always use these tools when helpful to provide context, summaries, and inspiration.
Today is {{ $now }}.</code></pre><p>In <em>n8n&#8217;s</em> world, an <em>AI Agent</em> is &#8220;<em>an autonomous system that receives data, makes decisions, and acts within its environment</em>&#8221;. By attaching my own tools to it, I give it power to look up information and craft answers.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Gw4v!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c1893af-dbd4-4102-894d-0d2c09f03d20_856x1403.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Gw4v!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c1893af-dbd4-4102-894d-0d2c09f03d20_856x1403.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Gw4v!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c1893af-dbd4-4102-894d-0d2c09f03d20_856x1403.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Gw4v!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c1893af-dbd4-4102-894d-0d2c09f03d20_856x1403.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Gw4v!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c1893af-dbd4-4102-894d-0d2c09f03d20_856x1403.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Gw4v!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c1893af-dbd4-4102-894d-0d2c09f03d20_856x1403.jpeg" width="856" height="1403" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0c1893af-dbd4-4102-894d-0d2c09f03d20_856x1403.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1403,&quot;width&quot;:856,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:161151,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/174357207?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c1893af-dbd4-4102-894d-0d2c09f03d20_856x1403.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Gw4v!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c1893af-dbd4-4102-894d-0d2c09f03d20_856x1403.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Gw4v!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c1893af-dbd4-4102-894d-0d2c09f03d20_856x1403.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Gw4v!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c1893af-dbd4-4102-894d-0d2c09f03d20_856x1403.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Gw4v!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c1893af-dbd4-4102-894d-0d2c09f03d20_856x1403.jpeg 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 role="img" 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><title></title><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>OpenAI Chat (GPT-4.1).</strong> This chat model node calls OpenAI&#8217;s chat completion (using <em>GPT-4.1</em>). It is the &#8220;<em>brain</em>&#8221; of the agent.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!zi9e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9abedfaa-e7f3-4e54-b094-12cb66fe9fce_835x712.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!zi9e!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9abedfaa-e7f3-4e54-b094-12cb66fe9fce_835x712.jpeg 424w, https://substackcdn.com/image/fetch/$s_!zi9e!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9abedfaa-e7f3-4e54-b094-12cb66fe9fce_835x712.jpeg 848w, https://substackcdn.com/image/fetch/$s_!zi9e!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9abedfaa-e7f3-4e54-b094-12cb66fe9fce_835x712.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!zi9e!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9abedfaa-e7f3-4e54-b094-12cb66fe9fce_835x712.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!zi9e!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9abedfaa-e7f3-4e54-b094-12cb66fe9fce_835x712.jpeg" width="835" height="712" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9abedfaa-e7f3-4e54-b094-12cb66fe9fce_835x712.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:712,&quot;width&quot;:835,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:58482,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/174357207?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9abedfaa-e7f3-4e54-b094-12cb66fe9fce_835x712.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!zi9e!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9abedfaa-e7f3-4e54-b094-12cb66fe9fce_835x712.jpeg 424w, https://substackcdn.com/image/fetch/$s_!zi9e!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9abedfaa-e7f3-4e54-b094-12cb66fe9fce_835x712.jpeg 848w, https://substackcdn.com/image/fetch/$s_!zi9e!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9abedfaa-e7f3-4e54-b094-12cb66fe9fce_835x712.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!zi9e!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9abedfaa-e7f3-4e54-b094-12cb66fe9fce_835x712.jpeg 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 role="img" 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><title></title><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>Whenever the agent decides it needs to generate text (like an answer or idea list), it uses this node. </p><p><strong>Memory Buffer</strong>. I added a <em>Simple Memory</em> node. This stores our chat history so the agent can refer back to earlier messages. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1lP7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1116f004-c7e0-45e4-be15-2bf5f10c5dad_841x708.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1lP7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1116f004-c7e0-45e4-be15-2bf5f10c5dad_841x708.jpeg 424w, https://substackcdn.com/image/fetch/$s_!1lP7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1116f004-c7e0-45e4-be15-2bf5f10c5dad_841x708.jpeg 848w, https://substackcdn.com/image/fetch/$s_!1lP7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1116f004-c7e0-45e4-be15-2bf5f10c5dad_841x708.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!1lP7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1116f004-c7e0-45e4-be15-2bf5f10c5dad_841x708.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1lP7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1116f004-c7e0-45e4-be15-2bf5f10c5dad_841x708.jpeg" width="841" height="708" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1116f004-c7e0-45e4-be15-2bf5f10c5dad_841x708.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:708,&quot;width&quot;:841,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:60324,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/174357207?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1116f004-c7e0-45e4-be15-2bf5f10c5dad_841x708.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1lP7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1116f004-c7e0-45e4-be15-2bf5f10c5dad_841x708.jpeg 424w, https://substackcdn.com/image/fetch/$s_!1lP7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1116f004-c7e0-45e4-be15-2bf5f10c5dad_841x708.jpeg 848w, https://substackcdn.com/image/fetch/$s_!1lP7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1116f004-c7e0-45e4-be15-2bf5f10c5dad_841x708.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!1lP7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1116f004-c7e0-45e4-be15-2bf5f10c5dad_841x708.jpeg 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 role="img" 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><title></title><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>In practice, this means if I say &#8220;<em>following up on the idea about AI in education</em>&#8221;, the agent still remembers what we talked about before.</p><p>Inside the agent node, I hook up a few <strong>Substack Tools</strong>. Crucially, I created custom sub-nodes that call the <em>Substack API</em>. These tools let the agent fetch my content. </p><div class="image-gallery-embed" data-attrs="{&quot;gallery&quot;:{&quot;images&quot;:[{&quot;type&quot;:&quot;image/jpeg&quot;,&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a010e86c-7c3e-4348-b783-a7d4084f5fbe_845x946.jpeg&quot;},{&quot;type&quot;:&quot;image/jpeg&quot;,&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d98d0e18-b1b2-40e4-9b30-ad199d437e39_837x940.jpeg&quot;},{&quot;type&quot;:&quot;image/jpeg&quot;,&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fcb7ea28-035a-401d-8822-f0a7fc567584_819x951.jpeg&quot;}],&quot;caption&quot;:&quot;&quot;,&quot;alt&quot;:&quot;Substack Tools&quot;,&quot;staticGalleryImage&quot;:{&quot;type&quot;:&quot;image/png&quot;,&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f881e6d6-ef2d-41cc-9963-9043338d657d_1456x474.png&quot;}},&quot;isEditorNode&quot;:true}"></div><p>For example, one tool calls &#8220;<em>Get All Posts</em>&#8221; to grab the titles or previews of my most recent articles. Another tool calls &#8220;<em>Get Post by ID</em>&#8221; to fetch an entire post&#8217;s content.  So if I ask &#8220;<em>What&#8217;s in post #123?</em>&#8221;, the agent uses the <em>Substack</em> tool to retrieve that post text and then passes it to the <em>GPT</em> model to summarize or analyze.</p><p>Because all these are connected, the agent intelligently decides when to use which tool. For example, if I type &#8220;<em>Show me my latest post</em>&#8221;, the agent might call the &#8220;<em>Get All Posts</em>&#8221; tool and &#8220;<em>Get Post by ID</em>&#8220; under the hood and then display the results. It can even call multiple tools in one answer if needed.</p><h2>&#9986;&#65039;&#129534; <strong>Code Node</strong></h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ZLba!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09471331-45bc-479c-834d-99788a25f81f_439x381.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ZLba!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09471331-45bc-479c-834d-99788a25f81f_439x381.jpeg 424w, https://substackcdn.com/image/fetch/$s_!ZLba!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09471331-45bc-479c-834d-99788a25f81f_439x381.jpeg 848w, https://substackcdn.com/image/fetch/$s_!ZLba!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09471331-45bc-479c-834d-99788a25f81f_439x381.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!ZLba!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09471331-45bc-479c-834d-99788a25f81f_439x381.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ZLba!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09471331-45bc-479c-834d-99788a25f81f_439x381.jpeg" width="439" height="381" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/09471331-45bc-479c-834d-99788a25f81f_439x381.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:381,&quot;width&quot;:439,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:18200,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/174357207?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09471331-45bc-479c-834d-99788a25f81f_439x381.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ZLba!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09471331-45bc-479c-834d-99788a25f81f_439x381.jpeg 424w, https://substackcdn.com/image/fetch/$s_!ZLba!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09471331-45bc-479c-834d-99788a25f81f_439x381.jpeg 848w, https://substackcdn.com/image/fetch/$s_!ZLba!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09471331-45bc-479c-834d-99788a25f81f_439x381.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!ZLba!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09471331-45bc-479c-834d-99788a25f81f_439x381.jpeg 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 role="img" 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><title></title><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>After the AI agent generates a response, it might be several hundred words long. I added a <em>Code</em> node next in line to handle splitting. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!kE-n!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14cd818f-de74-4879-8610-fbf5d8c4a13f_1601x1377.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!kE-n!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14cd818f-de74-4879-8610-fbf5d8c4a13f_1601x1377.jpeg 424w, https://substackcdn.com/image/fetch/$s_!kE-n!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14cd818f-de74-4879-8610-fbf5d8c4a13f_1601x1377.jpeg 848w, https://substackcdn.com/image/fetch/$s_!kE-n!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14cd818f-de74-4879-8610-fbf5d8c4a13f_1601x1377.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!kE-n!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14cd818f-de74-4879-8610-fbf5d8c4a13f_1601x1377.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!kE-n!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14cd818f-de74-4879-8610-fbf5d8c4a13f_1601x1377.jpeg" width="1456" height="1252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/14cd818f-de74-4879-8610-fbf5d8c4a13f_1601x1377.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1252,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:194596,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/174357207?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14cd818f-de74-4879-8610-fbf5d8c4a13f_1601x1377.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!kE-n!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14cd818f-de74-4879-8610-fbf5d8c4a13f_1601x1377.jpeg 424w, https://substackcdn.com/image/fetch/$s_!kE-n!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14cd818f-de74-4879-8610-fbf5d8c4a13f_1601x1377.jpeg 848w, https://substackcdn.com/image/fetch/$s_!kE-n!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14cd818f-de74-4879-8610-fbf5d8c4a13f_1601x1377.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!kE-n!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14cd818f-de74-4879-8610-fbf5d8c4a13f_1601x1377.jpeg 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 role="img" 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><title></title><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>This node runs a bit of <em>JavaScript</em> that takes the agent&#8217;s output text and breaks it into an array of chunks, each under 1000 characters. </p><pre><code>const inputText = $input.first().json.output || "";
const lines = inputText.split("\n");

let output = [];
let currentChunk = "";

for (const line of lines) {
  if ((currentChunk + line + "\n").length &gt; 1000) {
    if (currentChunk) output.push(currentChunk.trim());
    currentChunk = line + "\n";
  } else {
    currentChunk += line + "\n";
  }
}
if (currentChunk) output.push(currentChunk.trim());
return { output }</code></pre><p>This is necessary because <em>Telegram</em> messages have a character limit and we want to avoid cutting anything off. Think of this node as a smart text buffer: <strong>it makes sure each piece is short enough to send</strong>.</p><div><hr></div><p>&#129300; The workflow I built connects quite a few moving parts. If something isn&#8217;t clear or you&#8217;d like me to break down a specific step in more detail, <strong>drop a comment below</strong>. I check them all and I&#8217;m happy to help troubleshoot or brainstorm improvements together.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/supercharge-your-substack-build-a/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/supercharge-your-substack-build-a/comments"><span>Leave a comment</span></a></p><div><hr></div><h2>&#128256;&#128228; <strong>Split Out Node</strong></h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!KX5v!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6c163d2-ab16-498f-b8dc-fa48a80ed512_325x384.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!KX5v!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6c163d2-ab16-498f-b8dc-fa48a80ed512_325x384.jpeg 424w, https://substackcdn.com/image/fetch/$s_!KX5v!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6c163d2-ab16-498f-b8dc-fa48a80ed512_325x384.jpeg 848w, https://substackcdn.com/image/fetch/$s_!KX5v!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6c163d2-ab16-498f-b8dc-fa48a80ed512_325x384.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!KX5v!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6c163d2-ab16-498f-b8dc-fa48a80ed512_325x384.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!KX5v!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6c163d2-ab16-498f-b8dc-fa48a80ed512_325x384.jpeg" width="325" height="384" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d6c163d2-ab16-498f-b8dc-fa48a80ed512_325x384.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:384,&quot;width&quot;:325,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:14716,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/174357207?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6c163d2-ab16-498f-b8dc-fa48a80ed512_325x384.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!KX5v!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6c163d2-ab16-498f-b8dc-fa48a80ed512_325x384.jpeg 424w, https://substackcdn.com/image/fetch/$s_!KX5v!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6c163d2-ab16-498f-b8dc-fa48a80ed512_325x384.jpeg 848w, https://substackcdn.com/image/fetch/$s_!KX5v!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6c163d2-ab16-498f-b8dc-fa48a80ed512_325x384.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!KX5v!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6c163d2-ab16-498f-b8dc-fa48a80ed512_325x384.jpeg 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 role="img" 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><title></title><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>Next, a <em>Split Out</em> node takes that array of text chunks and splits them into separate &#8220;<em>items</em>&#8221; in <em>n8n&#8217;s</em> workflow. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4JoB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb6a4aee-5b74-4a9a-99a0-319da849e016_849x710.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4JoB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb6a4aee-5b74-4a9a-99a0-319da849e016_849x710.jpeg 424w, https://substackcdn.com/image/fetch/$s_!4JoB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb6a4aee-5b74-4a9a-99a0-319da849e016_849x710.jpeg 848w, https://substackcdn.com/image/fetch/$s_!4JoB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb6a4aee-5b74-4a9a-99a0-319da849e016_849x710.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!4JoB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb6a4aee-5b74-4a9a-99a0-319da849e016_849x710.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4JoB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb6a4aee-5b74-4a9a-99a0-319da849e016_849x710.jpeg" width="849" height="710" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bb6a4aee-5b74-4a9a-99a0-319da849e016_849x710.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:710,&quot;width&quot;:849,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:54381,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/174357207?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb6a4aee-5b74-4a9a-99a0-319da849e016_849x710.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!4JoB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb6a4aee-5b74-4a9a-99a0-319da849e016_849x710.jpeg 424w, https://substackcdn.com/image/fetch/$s_!4JoB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb6a4aee-5b74-4a9a-99a0-319da849e016_849x710.jpeg 848w, https://substackcdn.com/image/fetch/$s_!4JoB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb6a4aee-5b74-4a9a-99a0-319da849e016_849x710.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!4JoB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb6a4aee-5b74-4a9a-99a0-319da849e016_849x710.jpeg 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 role="img" 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><title></title><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>Essentially, if the code node created an array like ["<em>Hello world...</em>", "<em>How are you?</em>", ""], the <em>Split Out</em> node will produce three output items from it (ignoring any empty tail). This sets us up to send each chunk as a separate message.</p><h2>&#128260;&#128230; <strong>Loop Over Items node</strong></h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cYUg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ba7dfc2-126a-42df-a145-37cb63eff205_408x382.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cYUg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ba7dfc2-126a-42df-a145-37cb63eff205_408x382.jpeg 424w, https://substackcdn.com/image/fetch/$s_!cYUg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ba7dfc2-126a-42df-a145-37cb63eff205_408x382.jpeg 848w, https://substackcdn.com/image/fetch/$s_!cYUg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ba7dfc2-126a-42df-a145-37cb63eff205_408x382.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!cYUg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ba7dfc2-126a-42df-a145-37cb63eff205_408x382.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cYUg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ba7dfc2-126a-42df-a145-37cb63eff205_408x382.jpeg" width="408" height="382" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9ba7dfc2-126a-42df-a145-37cb63eff205_408x382.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:382,&quot;width&quot;:408,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:19614,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/174357207?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ba7dfc2-126a-42df-a145-37cb63eff205_408x382.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!cYUg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ba7dfc2-126a-42df-a145-37cb63eff205_408x382.jpeg 424w, https://substackcdn.com/image/fetch/$s_!cYUg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ba7dfc2-126a-42df-a145-37cb63eff205_408x382.jpeg 848w, https://substackcdn.com/image/fetch/$s_!cYUg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ba7dfc2-126a-42df-a145-37cb63eff205_408x382.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!cYUg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ba7dfc2-126a-42df-a145-37cb63eff205_408x382.jpeg 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 role="img" 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><title></title><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>Now I use a <em>Loop Over Items</em> node to handle each chunk one by one. This node goes through each split message in order. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LyY4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68d49261-cddd-47e2-932e-56202f2dc5f2_836x679.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LyY4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68d49261-cddd-47e2-932e-56202f2dc5f2_836x679.jpeg 424w, https://substackcdn.com/image/fetch/$s_!LyY4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68d49261-cddd-47e2-932e-56202f2dc5f2_836x679.jpeg 848w, https://substackcdn.com/image/fetch/$s_!LyY4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68d49261-cddd-47e2-932e-56202f2dc5f2_836x679.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!LyY4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68d49261-cddd-47e2-932e-56202f2dc5f2_836x679.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LyY4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68d49261-cddd-47e2-932e-56202f2dc5f2_836x679.jpeg" width="836" height="679" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/68d49261-cddd-47e2-932e-56202f2dc5f2_836x679.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:679,&quot;width&quot;:836,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:60388,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/174357207?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68d49261-cddd-47e2-932e-56202f2dc5f2_836x679.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!LyY4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68d49261-cddd-47e2-932e-56202f2dc5f2_836x679.jpeg 424w, https://substackcdn.com/image/fetch/$s_!LyY4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68d49261-cddd-47e2-932e-56202f2dc5f2_836x679.jpeg 848w, https://substackcdn.com/image/fetch/$s_!LyY4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68d49261-cddd-47e2-932e-56202f2dc5f2_836x679.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!LyY4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68d49261-cddd-47e2-932e-56202f2dc5f2_836x679.jpeg 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 role="img" 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><title></title><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>On each loop iteration, it takes the next text chunk and passes it to the <em>Telegram</em> reply node. In <em>n8n</em> terms, this ensures the messages are sent sequentially so nothing gets lost. It&#8217;s basically a loop that says &#8220;<em>for each piece of text, do the next step</em>&#8221;.</p><h2>&#128172;&#128236; <strong>Telegram Reply node</strong></h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CgEm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb3a631d-8d68-4910-afd9-af621112d720_406x419.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CgEm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb3a631d-8d68-4910-afd9-af621112d720_406x419.jpeg 424w, https://substackcdn.com/image/fetch/$s_!CgEm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb3a631d-8d68-4910-afd9-af621112d720_406x419.jpeg 848w, https://substackcdn.com/image/fetch/$s_!CgEm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb3a631d-8d68-4910-afd9-af621112d720_406x419.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!CgEm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb3a631d-8d68-4910-afd9-af621112d720_406x419.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CgEm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb3a631d-8d68-4910-afd9-af621112d720_406x419.jpeg" width="406" height="419" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/db3a631d-8d68-4910-afd9-af621112d720_406x419.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:419,&quot;width&quot;:406,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:24232,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/174357207?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb3a631d-8d68-4910-afd9-af621112d720_406x419.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!CgEm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb3a631d-8d68-4910-afd9-af621112d720_406x419.jpeg 424w, https://substackcdn.com/image/fetch/$s_!CgEm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb3a631d-8d68-4910-afd9-af621112d720_406x419.jpeg 848w, https://substackcdn.com/image/fetch/$s_!CgEm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb3a631d-8d68-4910-afd9-af621112d720_406x419.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!CgEm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb3a631d-8d68-4910-afd9-af621112d720_406x419.jpeg 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 role="img" 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><title></title><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>Finally, a <em>Telegram </em>Reply node sends the text chunk back into the <em>Telegram</em> chat. Each loop iteration triggers this node once, so the user (me) sees multiple messages in sequence that together make up the full answer. I configured it to reply in the <strong>same chat ID</strong>. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!wkFi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0ea4865-be01-4776-ae4d-7859dd344d90_848x1262.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!wkFi!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0ea4865-be01-4776-ae4d-7859dd344d90_848x1262.jpeg 424w, https://substackcdn.com/image/fetch/$s_!wkFi!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0ea4865-be01-4776-ae4d-7859dd344d90_848x1262.jpeg 848w, https://substackcdn.com/image/fetch/$s_!wkFi!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0ea4865-be01-4776-ae4d-7859dd344d90_848x1262.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!wkFi!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0ea4865-be01-4776-ae4d-7859dd344d90_848x1262.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!wkFi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0ea4865-be01-4776-ae4d-7859dd344d90_848x1262.jpeg" width="848" height="1262" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b0ea4865-be01-4776-ae4d-7859dd344d90_848x1262.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1262,&quot;width&quot;:848,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:103178,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/174357207?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0ea4865-be01-4776-ae4d-7859dd344d90_848x1262.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!wkFi!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0ea4865-be01-4776-ae4d-7859dd344d90_848x1262.jpeg 424w, https://substackcdn.com/image/fetch/$s_!wkFi!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0ea4865-be01-4776-ae4d-7859dd344d90_848x1262.jpeg 848w, https://substackcdn.com/image/fetch/$s_!wkFi!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0ea4865-be01-4776-ae4d-7859dd344d90_848x1262.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!wkFi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0ea4865-be01-4776-ae4d-7859dd344d90_848x1262.jpeg 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 role="img" 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><title></title><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>Optionally, there&#8217;s a setting to mask or escape any <em>HTML/Markdown</em> (<em>n8n&#8217;s</em> docs even mention using a special node to mask <em>HTML</em> syntax for stability ). In practice, this means I get all the parts of the answer delivered one after the other as tidy messages on <em>Telegram</em>.</p><p>This covers the main nodes; the flow is: <strong>(1) Telegram Trigger &#8594; (2) AI Agent (with tools) &#8594; (3) Code split &#8594; (4) Split Out &#8594; (5) Loop &#8594; (6) Telegram Reply.</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7eTk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73ec3d67-4723-4b61-a6d0-d3b6ec712ec6_1195x978.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7eTk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73ec3d67-4723-4b61-a6d0-d3b6ec712ec6_1195x978.jpeg 424w, https://substackcdn.com/image/fetch/$s_!7eTk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73ec3d67-4723-4b61-a6d0-d3b6ec712ec6_1195x978.jpeg 848w, https://substackcdn.com/image/fetch/$s_!7eTk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73ec3d67-4723-4b61-a6d0-d3b6ec712ec6_1195x978.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!7eTk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73ec3d67-4723-4b61-a6d0-d3b6ec712ec6_1195x978.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7eTk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73ec3d67-4723-4b61-a6d0-d3b6ec712ec6_1195x978.jpeg" width="725.1666259765625" height="593.4836487071783" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/73ec3d67-4723-4b61-a6d0-d3b6ec712ec6_1195x978.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:978,&quot;width&quot;:1195,&quot;resizeWidth&quot;:725.1666259765625,&quot;bytes&quot;:218672,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/174357207?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45ce6814-7a4f-48af-bf33-80e1cdcf5085_1195x1150.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!7eTk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73ec3d67-4723-4b61-a6d0-d3b6ec712ec6_1195x978.jpeg 424w, https://substackcdn.com/image/fetch/$s_!7eTk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73ec3d67-4723-4b61-a6d0-d3b6ec712ec6_1195x978.jpeg 848w, https://substackcdn.com/image/fetch/$s_!7eTk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73ec3d67-4723-4b61-a6d0-d3b6ec712ec6_1195x978.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!7eTk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F73ec3d67-4723-4b61-a6d0-d3b6ec712ec6_1195x978.jpeg 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 role="img" 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><title></title><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>Each node&#8217;s output feeds into the next, so a <em>Telegram</em> message goes in, data flows through the agent tools, and replies come back chunk by chunk.</p><h1>&#128273;&#127760; <strong>Getting API keys</strong></h1><p>Before running this workflow, you need API keys/credentials for each service.</p><h2><strong>OpenAI API key</strong></h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!AaKP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27979f41-3671-443f-bb81-2b7810d2b000_1865x493.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!AaKP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27979f41-3671-443f-bb81-2b7810d2b000_1865x493.png 424w, https://substackcdn.com/image/fetch/$s_!AaKP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27979f41-3671-443f-bb81-2b7810d2b000_1865x493.png 848w, https://substackcdn.com/image/fetch/$s_!AaKP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27979f41-3671-443f-bb81-2b7810d2b000_1865x493.png 1272w, https://substackcdn.com/image/fetch/$s_!AaKP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27979f41-3671-443f-bb81-2b7810d2b000_1865x493.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!AaKP!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27979f41-3671-443f-bb81-2b7810d2b000_1865x493.png" width="1200" height="317.2117962466488" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/27979f41-3671-443f-bb81-2b7810d2b000_1865x493.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:493,&quot;width&quot;:1865,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:76181,&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://iam.slys.dev/i/174357207?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5cafc9f-b6da-458b-876b-8a8be38240ee_1920x1080.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!AaKP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27979f41-3671-443f-bb81-2b7810d2b000_1865x493.png 424w, https://substackcdn.com/image/fetch/$s_!AaKP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27979f41-3671-443f-bb81-2b7810d2b000_1865x493.png 848w, https://substackcdn.com/image/fetch/$s_!AaKP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27979f41-3671-443f-bb81-2b7810d2b000_1865x493.png 1272w, https://substackcdn.com/image/fetch/$s_!AaKP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27979f41-3671-443f-bb81-2b7810d2b000_1865x493.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 role="img" 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><title></title><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>Go to <a href="https://platform.openai.com">OpenAI Platform</a> and sign up or log in. In the dashboard, click your account icon and select API keys. Then click <em>Create new secret key</em> to generate a key. Copy that key (you won&#8217;t be able to see it again) and add it as credentials in <em>n8n</em>. This lets the AI Agent node call <em>GPT-4.1</em> via <em>OpenAI&#8217;s</em> <em>API</em>.</p><h2><strong>Substack credentials</strong></h2><p>I used unofficial <em>Substack</em> <em>API</em> along with <em>Substack</em> community node for this. To make it work, I had to obtain <em>Substack</em> credentials/API key. This part is a bit tricky, but you can learn how to do it the following post.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;8018e25f-7319-49d6-b361-827698694e1d&quot;,&quot;caption&quot;:&quot;In my last post, I chronicled how I reverse-engineered Substack&#8217;s hidden API to build an unofficial javascript client. It was a deep dive into Substack&#8217;s inner workings &#8211; fun for code enthusiasts, but not exactly accessible to everyone. Ever since, I&#8217;ve been itching to make&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Substack automation with n8n: how to publish Notes automatically &#128640;&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:254824415,&quot;name&quot;:&quot;Jakub Slys &#127894;&#65039;&quot;,&quot;bio&quot;:&quot;Ever wonder how Uber matches rides &#128663; in seconds or how OpenAI &#129302; chats like a human? &#128187; Engineer @ Pega | ex-Sabre | ex-Nokia&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4d17c584-3500-4a83-9db9-f826c356ee62_2000x2000.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-08-15T13:08:12.190Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!5bth!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc9f58de-1b2e-4010-94ff-b26091d39380_1536x1024.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://iam.slys.dev/p/substack-automation-with-n8n-how&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:170924044,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:136,&quot;comment_count&quot;:58,&quot;publication_id&quot;:2817779,&quot;publication_name&quot;:&quot;slys.dev&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!9q0E!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3b67508-e73c-434b-89ae-fde2c72e8fa4_256x256.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><h2><strong>Telegram Bot API token</strong></h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!blSX!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4d7462f-7321-42fd-a5ae-c45dea4f73dc_736x999.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!blSX!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4d7462f-7321-42fd-a5ae-c45dea4f73dc_736x999.jpeg 424w, https://substackcdn.com/image/fetch/$s_!blSX!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4d7462f-7321-42fd-a5ae-c45dea4f73dc_736x999.jpeg 848w, https://substackcdn.com/image/fetch/$s_!blSX!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4d7462f-7321-42fd-a5ae-c45dea4f73dc_736x999.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!blSX!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4d7462f-7321-42fd-a5ae-c45dea4f73dc_736x999.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!blSX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4d7462f-7321-42fd-a5ae-c45dea4f73dc_736x999.jpeg" width="736" height="999" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b4d7462f-7321-42fd-a5ae-c45dea4f73dc_736x999.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:999,&quot;width&quot;:736,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:112505,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/174357207?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4d7462f-7321-42fd-a5ae-c45dea4f73dc_736x999.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!blSX!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4d7462f-7321-42fd-a5ae-c45dea4f73dc_736x999.jpeg 424w, https://substackcdn.com/image/fetch/$s_!blSX!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4d7462f-7321-42fd-a5ae-c45dea4f73dc_736x999.jpeg 848w, https://substackcdn.com/image/fetch/$s_!blSX!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4d7462f-7321-42fd-a5ae-c45dea4f73dc_736x999.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!blSX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4d7462f-7321-42fd-a5ae-c45dea4f73dc_736x999.jpeg 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 role="img" 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><title></title><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>Open the Telegram app and start a chat with <strong>@BotFather</strong>. Send <code>/newbot</code> and follow the prompts to name your bot and set its username. <em>BotFather</em> will reply with a message that includes <strong>your new bot&#8217;s API token</strong>. (It looks like <code>123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11</code>). Copy this token into <em>n8n&#8217;s</em> <em>Telegram</em> credentials. Now your workflow can connect to that bot and send/reply to messages.</p><p>Each of these steps only takes a few minutes. Once the keys are stored in <em>n8n</em>, my workflow nodes could authenticate to <em>OpenAI</em>, <em>Substack</em>, and <em>Telegram</em> seamlessly.</p><div><hr></div><p>&#128588; This guide took a lot of tinkering (and coffee &#9749;) to put together, but I truly believe it can save creators hours of work. If it sparked new ideas for you, please hit <strong>Share</strong> so others can discover it too - let&#8217;s spread the word and help more people build smarter with AI.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/supercharge-your-substack-build-a?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/supercharge-your-substack-build-a?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div><hr></div><h1><strong>&#10024;&#128588; Recap</strong></h1><p>Putting this all together, I ended up with a smart, <em>Telegram</em>-based assistant for my newsletter work. It responds to my messages, knows my recent <em>Substack</em> content, and helps me generate or refine ideas. The AI agent, armed with <em>GPT-4.1</em> and a memory buffer, can chat naturally and reference past notes. And by chunking outputs for <em>Telegram</em>, nothing gets cut off.</p><p>This assistant saves me a ton of time. Instead of manually digging through my <em>Substack</em> or brainstorming alone, I just text the bot: &#8220;<em>Any ideas for this week&#8217;s topic?</em>&#8221; or &#8220;<em>Summarize my last post</em>&#8221;. It&#8217;s like having a personal AI editor in my pocket. Best of all, since <em>n8n</em> is so flexible, I can keep customizing and extending this workflow. For example, I could add a tool that scrapes <em>RSS</em> feeds, or connect it to <em>Google Sheets</em> to log ideas &#8211; <em>n8n</em> makes it easy to plug in new steps.</p><p>I hope this walk-through shows how even <em>no-code/low-code</em> developers can build something awesome. If you have your own newsletter or content pipeline, try adapting this setup. Swap in your <em>Substack</em> (or <em>Medium</em>, or blog <em>RSS</em>), or use a different messaging app &#8211; the pieces will be similar. The key idea is: <strong>chain the tools you need in </strong><em><strong>n8n</strong></em><strong>, give an agent a good prompt, and let </strong><em><strong>GPT-4.1</strong></em><strong> do the heavy lifting.</strong></p><p>Happy automating &#10024; &#8211; and may your content ideas flow freely with a little AI help!</p><div><hr></div><p><strong>&#128230;&#9889; Want to skip the setup and dive right in?</strong></p><p>Grab my exported workflow JSON below - just copy-paste it into your own <em>n8n</em> instance and you&#8217;re ready to roll!</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;265563c4-29be-4638-b707-aca5ff5cec0b&quot;,&quot;caption&quot;:&quot;This workflow powers a personalized AI assistant that helps brainstorm newsletter ideas using your own Substack content. It works by:&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Personalized AI assistant for Substack &#128640;&#129302; (JSON)&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:254824415,&quot;name&quot;:&quot;Jakub Slys &#127894;&#65039;&quot;,&quot;bio&quot;:&quot;Ever wonder how Uber matches rides &#128663; in seconds or how OpenAI &#129302; chats like a human? &#128187; Engineer @ Pega | ex-Sabre | ex-Nokia&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4d17c584-3500-4a83-9db9-f826c356ee62_2000x2000.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-09-24T18:39:42.527Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!tT6D!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a2c4239-1c12-4a76-a1e9-6050aa948f9b_1456x971.webp&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://iam.slys.dev/p/personalized-ai-assistant-for-substack&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:174466307,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:2817779,&quot;publication_name&quot;:&quot;slys.dev&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!9q0E!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3b67508-e73c-434b-89ae-fde2c72e8fa4_256x256.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><div><hr></div><p>&#10024; If you enjoyed this walk-through and want more practical tutorials, behind-the-scenes experiments, and honest lessons from my own journey, hit <strong>Subscribe</strong> now. <strong>Don&#8217;t miss the next post</strong> - your future AI assistant might be just one click away.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/subscribe?"><span>Subscribe now</span></a></p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p><a href="https://n8n.io/features/">Think it. Build it. Extend it. Simple enough to ship in hours, sophisticated enough to scale. n8n lets you automate business processes without limits on your logic. </a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p><a href="https://telegram.org/">Telegram. A new era of messaging.</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p><a href="https://n8n.io/workflows/2035-telegram-ai-bot-with-langchain-nodes/">Telegram AI bot with LangChain nodes</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-4" href="#footnote-anchor-4" class="footnote-number" contenteditable="false" target="_self">4</a><div class="footnote-content"><p><a href="https://core.telegram.org/bots/tutorial">From BotFather to &#8216;Hello World&#8217;</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-5" href="#footnote-anchor-5" class="footnote-number" contenteditable="false" target="_self">5</a><div class="footnote-content"><p><a href="https://openai.com/index/gpt-4-1/">Introducing GPT-4.1 in the API</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-6" href="#footnote-anchor-6" class="footnote-number" contenteditable="false" target="_self">6</a><div class="footnote-content"><p><a href="https://substack-api.readthedocs.io/">Substack API client documentation</a></p></div></div>]]></content:encoded></item><item><title><![CDATA[Substack Notes Scheduler (JSON)]]></title><description><![CDATA[Save time, stay consistent, and let automation handle the posting for you!]]></description><link>https://iam.slys.dev/p/substack-notes-scheduler-json</link><guid isPermaLink="false">https://iam.slys.dev/p/substack-notes-scheduler-json</guid><dc:creator><![CDATA[Jakub Slys 🤖]]></dc:creator><pubDate>Tue, 23 Sep 2025 13:58:40 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Nbiy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffde38c4b-18d6-420f-a9af-1597ff568b35_1536x1024.jpeg" 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_!Nbiy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffde38c4b-18d6-420f-a9af-1597ff568b35_1536x1024.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Nbiy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffde38c4b-18d6-420f-a9af-1597ff568b35_1536x1024.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Nbiy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffde38c4b-18d6-420f-a9af-1597ff568b35_1536x1024.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Nbiy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffde38c4b-18d6-420f-a9af-1597ff568b35_1536x1024.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Nbiy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffde38c4b-18d6-420f-a9af-1597ff568b35_1536x1024.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Nbiy!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffde38c4b-18d6-420f-a9af-1597ff568b35_1536x1024.jpeg" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fde38c4b-18d6-420f-a9af-1597ff568b35_1536x1024.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:101311,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://iam.slys.dev/i/174341594?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffde38c4b-18d6-420f-a9af-1597ff568b35_1536x1024.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Nbiy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffde38c4b-18d6-420f-a9af-1597ff568b35_1536x1024.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Nbiy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffde38c4b-18d6-420f-a9af-1597ff568b35_1536x1024.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Nbiy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffde38c4b-18d6-420f-a9af-1597ff568b35_1536x1024.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Nbiy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffde38c4b-18d6-420f-a9af-1597ff568b35_1536x1024.jpeg 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 role="img" 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><title></title><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>&#128230;&#9889; Want to skip the setup and dive right in?</strong> </p><p>Grab my exported workflow JSON below - just copy-paste it into your own n8n instance and you&#8217;re ready to roll!</p><pre><code>{
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 6
}
]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [
0,
0
],
"id": "0dd59a2c-726f-4e83-9607-20f12823cd6c",
"name": "Schedule Trigger"
},
{
"parameters": {
"documentId": {
"
__rl": true,
"value": "1o
_JDKcwWMRJVr1bxiBDELwU23YjMA78ZgCD1gAmFrHo",
"mode": "list",
"cachedResultName": "Substack Notes drafts",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1o_JDKcwWMRJVr1bxiBDELwU23YjMA78ZgCD1gAmFrHo/edit?usp=drivesdk"
},
"sheetName": {
"
__rl": true,
"value": "gid=0",
"mode": "list",
"cachedResultName": "Drafts",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1o_JDKcwWMRJVr1bxiBDELwU23YjMA78ZgCD1gAmFrHo/edit#gid=0"
},
"options": {}
},
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.7,
"position": [
208,
0
],
"id": "46151c11-5a98-4dac-960c-b509e08468f9",
"name": "Get row(s) in sheet",
"credentials": {
"googleSheetsOAuth2Api": {
"id": "xd4WsMz5QECK83x8",
"name": "Google Sheets account"
}
}
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": false,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "0b5f203b-cf72-484a-8298-37626d130daa",
"leftValue": "={{ $json.exhausted.toString() }}",
"rightValue": "true",
"operator": {
"type": "string",
"operation": "notEquals"
}
}
],
"combinator": "and"
},
"options": {
"ignoreCase": true
}
},
"type": "n8n-nodes-base.filter",
"typeVersion": 2.2,
"position": [
416,
0
],
"id": "ceaa4e45-47f0-4c54-9e1c-18efb7a56173",
"name": "Filter"
},
{
"parameters": {},
"type": "n8n-nodes-base.limit",
"typeVersion": 1,
"position": [
624,
0
],
"id": "2b74c81f-c715-4600-ad30-94b0653043f0",
"name": "Limit"
},
{
"parameters": {
"resource": "note",
"operation": "create",
"body": "={{ $json.content }}",
"contentType": "advanced",
"attachment": "link",
"linkUrl": "={{ $json.link }}"
},
"type": "n8n-nodes-substack.substack",
"typeVersion": 1,
"position": [
816,
0
],
"id": "70652a65-b24a-40b5-bd14-cce3805221ef",
"name": "Create note",
"credentials": {
"substackApi": {
"id": "S0ZbGy9f6anXZDSu",
"name": "Substack account"
}
}
},
{
"parameters": {
"operation": "appendOrUpdate",
"documentId": {
"
__rl": true,
"value": "1o
_JDKcwWMRJVr1bxiBDELwU23YjMA78ZgCD1gAmFrHo",
"mode": "list",
"cachedResultName": "Substack Notes drafts",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1o_JDKcwWMRJVr1bxiBDELwU23YjMA78ZgCD1gAmFrHo/edit?usp=drivesdk"
},
"sheetName": {
"
__rl": true,
"value": "gid=0",
"mode": "list",
"cachedResultName": "Drafts",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1o_JDKcwWMRJVr1bxiBDELwU23YjMA78ZgCD1gAmFrHo/edit#gid=0"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"exhausted": "TRUE",
"id": "={{ $('Limit').item.json.id }}"
},
"matchingColumns": [
"id"
],
"schema": [
{
"id": "id",
"displayName": "id",
"required": false,
"defaultMatch": true,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": false
},
{
"id": "link",
"displayName": "link",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": true
},
{
"id": "content",
"displayName": "content",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true,
"removed": true
},
{
"id": "exhausted",
"displayName": "exhausted",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.7,
"position": [
1024,
0
],
"id": "ece91640-59cb-418e-9d61-f43d8b06ce45",
"name": "Append or update row in sheet",
"credentials": {
"googleSheetsOAuth2Api": {
"id": "xd4WsMz5QECK83x8",
"name": "Google Sheets account"
}
}
}
],
"connections": {
"Schedule Trigger": {
"main": [
[
{
"node": "Get row(s) in sheet",
"type": "main",
"index": 0
}
]
]
},
"Get row(s) in sheet": {
"main": [
[
{
"node": "Filter",
"type": "main",
"index": 0
}
]
]
},
"Filter": {
"main": [
[
{
"node": "Limit",
"type": "main",
"index": 0
}
]
]
},
"Limit": {
"main": [
[
{
"node": "Create note",
"type": "main",
"index": 0
}
]
]
},
"Create note": {
"main": [
[
{
"node": "Append or update row in sheet",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {},
"meta": {
"templateCredsSetupCompleted": true,
"instanceId": "992ac2542863ba689f62908163525ecb734f9f80532de01b501f2657b08b56c0"
}
}</code></pre>]]></content:encoded></item><item><title><![CDATA[How you can build Substack Notes scheduler with n8n]]></title><description><![CDATA[Save time, stay consistent, and let automation handle the posting for you!]]></description><link>https://iam.slys.dev/p/how-you-can-build-substack-notes</link><guid isPermaLink="false">https://iam.slys.dev/p/how-you-can-build-substack-notes</guid><dc:creator><![CDATA[Jakub Slys 🤖]]></dc:creator><pubDate>Mon, 15 Sep 2025 18:20:18 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!S9Hb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8495595f-fdff-41a6-9a84-922a53bff6e8_1536x1024.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_!S9Hb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8495595f-fdff-41a6-9a84-922a53bff6e8_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset image2-full-screen"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!S9Hb!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8495595f-fdff-41a6-9a84-922a53bff6e8_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!S9Hb!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8495595f-fdff-41a6-9a84-922a53bff6e8_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!S9Hb!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8495595f-fdff-41a6-9a84-922a53bff6e8_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!S9Hb!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8495595f-fdff-41a6-9a84-922a53bff6e8_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!S9Hb!,w_5760,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8495595f-fdff-41a6-9a84-922a53bff6e8_1536x1024.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8495595f-fdff-41a6-9a84-922a53bff6e8_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;full&quot;,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2293336,&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://iam.slys.dev/i/173450539?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8495595f-fdff-41a6-9a84-922a53bff6e8_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-fullscreen" alt="" srcset="https://substackcdn.com/image/fetch/$s_!S9Hb!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8495595f-fdff-41a6-9a84-922a53bff6e8_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!S9Hb!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8495595f-fdff-41a6-9a84-922a53bff6e8_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!S9Hb!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8495595f-fdff-41a6-9a84-922a53bff6e8_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!S9Hb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8495595f-fdff-41a6-9a84-922a53bff6e8_1536x1024.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 role="img" 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><title></title><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 few months ago, I realized <strong>I was tired of manually posting </strong><em><strong>Substack</strong></em><strong> </strong><em><strong>Notes</strong></em><strong> every day</strong>. I&#8217;d wake up each morning and think, &#8220;<em>Oh no, did I remember to post a note today?</em>&#8221; Some days I&#8217;d get busy and forget entirely. It was a small daily task, but it added up to stress. I thought to myself: there <strong>has to be a way to schedule these notes</strong> so they go out automatically. Imagine writing a week&#8217;s worth of short posts in one sitting and letting them publish on their own &#8211; <em>huge time savings</em>! That&#8217;s when I decided to build a little automation system to handle it for me.</p><p>Fast forward to now: I have a <strong>workflow</strong> that runs like clockwork, <em>posting my Substack Notes for me while I relax</em>. In this post, I&#8217;ll share the story of how I set up that scheduling system using <em><strong>n8n</strong></em> (a no-code automation tool) and <em><strong>Google Sheets</strong></em> as my content source. I&#8217;ll also break down all the steps so <strong>beginners can follow along and build the same setup</strong>. Let&#8217;s dive in!</p><h1><strong>Why I needed to automate my notes publishing</strong></h1><p>I love writing short-form updates on <em>Substack Notes</em> (think of them like tweets, but on <em>Substack</em>). However, I didn&#8217;t love the <strong>daily routine of logging in and manually posting</strong>. Some days I&#8217;d remember in the morning, other days I&#8217;d be scrambling at midnight. I knew automating this process would free me from having to remember every day and ensure consistency for my readers. Plus, I tend to write notes in batches when I&#8217;m feeling inspired &#8211; wouldn&#8217;t it be nice to have those notes queued up?</p><p>The pain point hit one day when I nearly missed a daily note because I was traveling. I thought, &#8220;<em>Enough is enough &#8211; I should let a robot do this</em>&#8221;. I had heard of <em><strong>n8n</strong></em>, an automation tool that could string tasks together visually. In fact, n8n is an open-source workflow tool (imagine a more flexible, self-hostable <em>Zapier</em><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a>). You can run it for free and connect it to hundreds of apps, or even add custom integrations when needed &#8211; perfect for my use case of connecting <em>Substack</em> with other services. I already had some experience with n8n and had even built a <strong>custom </strong><em><strong>Substack</strong></em><strong> integration node</strong> for it previously. </p><p>This meant I had the building blocks ready: I just needed to design the workflow.</p><p><strong>My goal</strong>. Have an <em>n8n</em> workflow that triggers on a schedule (without me doing anything), grabs a random draft note from a list I maintain, publishes it to <em>Substack</em>, and marks it as used so it won&#8217;t post the same thing twice. All while I&#8217;m off doing other things. No more &#8220;<em>oops I forgot to post today</em>&#8221; moments!</p><div><hr></div><p><strong>&#128172;&#10024; Ever caught yourself forgetting to post or scrambling at midnight?</strong> </p><p>Share your story in the comments - I&#8217;d love to compare notes!</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/p/how-you-can-build-substack-notes/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/p/how-you-can-build-substack-notes/comments"><span>Leave a comment</span></a></p><div><hr></div><h1><strong>&#128736; The tools</strong></h1><p>Before jumping into the step-by-step, here&#8217;s a quick overview of the tools I used.</p><p><strong>n8n</strong><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a>. A no-code automation platform where you create workflows by connecting nodes. (<em>Think: visual scripting for integrating apps</em>). I self-host <em>n8n</em>, but you can use their cloud service too. If you&#8217;re new to <em>n8n</em>, it&#8217;s super flexible and allows custom code or community-built nodes. We&#8217;ll use it to orchestrate the whole process.</p><p><strong>Google Sheets</strong><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a>. I decided to store my draft notes in a <em>Google Sheet</em>. Each row in the sheet is a short note I&#8217;ve written in advance (in <em>Markdown</em> format). <em>Google Sheets</em> is handy because it&#8217;s easy to edit and accessible from anywhere. <em>n8n</em> has a built-in <em>Google Sheets</em> node that supports reading and updating rows, which is exactly what we need.</p><p><strong>Substack Notes</strong><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a>. This is the platform where the content ultimately goes. <em>Substack</em> <em>Notes</em> are the short posts on <em>Substack</em> (similar to tweets). </p><p><strong>n8n Substack Node</strong>. Currently, <em>Substack</em> doesn&#8217;t offer an official public API for publishing, so I used a community node for <em>Substack</em> in <em>n8n</em> that I had created earlier. This custom <em>Substack node</em> knows how to call <em>Substack&#8217;s</em> hidden API to create new notes programmatically. </p><blockquote><p><em>Under the hood it uses my Substack session cookie for authentication, since that&#8217;s the trick to act on my account without an API key, but more on that later.</em></p></blockquote><p>With these three pieces &#8211; <strong>scheduler</strong>, <strong>content source</strong>, and <em><strong>Substack</strong></em><strong> publisher</strong> &#8211; I was ready to build the automation. </p><h1>The workflow</h1><p>Now let&#8217;s walk through how to set it all up, step by step.</p><h2><strong>&#9200; Scheduling the workflow</strong></h2><p>The first piece of the puzzle was getting the workflow to run automatically at regular intervals. <em>n8n</em> makes this easy with a built-in <strong>Schedule trigger</strong> node. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6_ci!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76b31c3d-b845-478f-8732-1f88d3da3914_711x554.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6_ci!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76b31c3d-b845-478f-8732-1f88d3da3914_711x554.png 424w, https://substackcdn.com/image/fetch/$s_!6_ci!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76b31c3d-b845-478f-8732-1f88d3da3914_711x554.png 848w, https://substackcdn.com/image/fetch/$s_!6_ci!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76b31c3d-b845-478f-8732-1f88d3da3914_711x554.png 1272w, https://substackcdn.com/image/fetch/$s_!6_ci!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76b31c3d-b845-478f-8732-1f88d3da3914_711x554.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6_ci!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76b31c3d-b845-478f-8732-1f88d3da3914_711x554.png" width="711" height="554" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/76b31c3d-b845-478f-8732-1f88d3da3914_711x554.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:554,&quot;width&quot;:711,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:18712,&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://iam.slys.dev/i/173450539?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F879bcedc-77c7-4c95-8f8d-ae887fb8dafb_1920x1043.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_!6_ci!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76b31c3d-b845-478f-8732-1f88d3da3914_711x554.png 424w, https://substackcdn.com/image/fetch/$s_!6_ci!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76b31c3d-b845-478f-8732-1f88d3da3914_711x554.png 848w, https://substackcdn.com/image/fetch/$s_!6_ci!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76b31c3d-b845-478f-8732-1f88d3da3914_711x554.png 1272w, https://substackcdn.com/image/fetch/$s_!6_ci!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F76b31c3d-b845-478f-8732-1f88d3da3914_711x554.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 role="img" 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><title></title><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>I added a Schedule node as the start of my workflow and configured it to run every few hours. In my case, I set it to run roughly <strong>every 6 hours</strong>, so I&#8217;d get a few notes posted throughout the day without me intervening. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Q5a0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d448785-5580-4e5a-96d9-7da531278a2e_1025x570.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Q5a0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d448785-5580-4e5a-96d9-7da531278a2e_1025x570.png 424w, https://substackcdn.com/image/fetch/$s_!Q5a0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d448785-5580-4e5a-96d9-7da531278a2e_1025x570.png 848w, https://substackcdn.com/image/fetch/$s_!Q5a0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d448785-5580-4e5a-96d9-7da531278a2e_1025x570.png 1272w, https://substackcdn.com/image/fetch/$s_!Q5a0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d448785-5580-4e5a-96d9-7da531278a2e_1025x570.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Q5a0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d448785-5580-4e5a-96d9-7da531278a2e_1025x570.png" width="1025" height="570" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8d448785-5580-4e5a-96d9-7da531278a2e_1025x570.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:570,&quot;width&quot;:1025,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:82519,&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://iam.slys.dev/i/173450539?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc7a3c51-c34b-442a-9d23-c79078029ac2_1920x1043.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_!Q5a0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d448785-5580-4e5a-96d9-7da531278a2e_1025x570.png 424w, https://substackcdn.com/image/fetch/$s_!Q5a0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d448785-5580-4e5a-96d9-7da531278a2e_1025x570.png 848w, https://substackcdn.com/image/fetch/$s_!Q5a0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d448785-5580-4e5a-96d9-7da531278a2e_1025x570.png 1272w, https://substackcdn.com/image/fetch/$s_!Q5a0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d448785-5580-4e5a-96d9-7da531278a2e_1025x570.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 role="img" 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><title></title><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>You could just as easily set it for once a day at a specific time (like every morning at 9 AM) &#8211; <em>n8n&#8217;s</em> Schedule node supports a variety of schedules.</p><p>To configure the schedule, I opened the Schedule node settings in n8n and chose a simple interval.</p><blockquote><p> You can also use Schedule trigger node expressions if you&#8217;re comfortable with those.</p></blockquote><p>For example, to run every 6 hours, I selected an interval of 6 hours between executions. If I wanted a daily post, I might set it to &#8220;<em>every day at 09:00</em>&#8221;. The flexibility here is great: you can have your <em>Substack</em> notes go out <strong>exactly when you want</strong> &#8211; whether it&#8217;s multiple times per day or a specific weekly schedule.</p><p>Why Schedule trigger node? Because it&#8217;s a fire-and-forget trigger. Once I activate the workflow, <em>n8n&#8217;s</em> Schedule trigger node will ensure it runs on schedule. No need for me to click anything. This was crucial to meet my goal of &#8220;<em>automation that runs without me remembering to run it</em>&#8221;. &#128640;</p><blockquote><p><em>Side note: If you&#8217;re following along, add the Schedule node to your n8n canvas first and set the schedule as desired. This will be the starting node that kicks off the whole process at those times.</em></p></blockquote><h2><strong>&#128203; Reading draft notes from Google Sheets</strong></h2><p>Next, I needed a bunch of content ready to post. I created a <em>Google Sheet</em> called &#8220;<em><strong>Substack Notes drafts</strong></em>&#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_!j5qb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a941676-f58a-4a5d-9cac-c2f8f86e2c3b_1433x647.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!j5qb!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a941676-f58a-4a5d-9cac-c2f8f86e2c3b_1433x647.png 424w, https://substackcdn.com/image/fetch/$s_!j5qb!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a941676-f58a-4a5d-9cac-c2f8f86e2c3b_1433x647.png 848w, https://substackcdn.com/image/fetch/$s_!j5qb!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a941676-f58a-4a5d-9cac-c2f8f86e2c3b_1433x647.png 1272w, https://substackcdn.com/image/fetch/$s_!j5qb!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a941676-f58a-4a5d-9cac-c2f8f86e2c3b_1433x647.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!j5qb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a941676-f58a-4a5d-9cac-c2f8f86e2c3b_1433x647.png" width="1433" height="647" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2a941676-f58a-4a5d-9cac-c2f8f86e2c3b_1433x647.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:647,&quot;width&quot;:1433,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:143429,&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://iam.slys.dev/i/173450539?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2100606-7ece-434a-af3e-6791c9fb544a_1920x1043.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_!j5qb!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a941676-f58a-4a5d-9cac-c2f8f86e2c3b_1433x647.png 424w, https://substackcdn.com/image/fetch/$s_!j5qb!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a941676-f58a-4a5d-9cac-c2f8f86e2c3b_1433x647.png 848w, https://substackcdn.com/image/fetch/$s_!j5qb!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a941676-f58a-4a5d-9cac-c2f8f86e2c3b_1433x647.png 1272w, https://substackcdn.com/image/fetch/$s_!j5qb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a941676-f58a-4a5d-9cac-c2f8f86e2c3b_1433x647.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 role="img" 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><title></title><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>In this sheet, I have four main columns: one for the <em>Note Id (</em>identifies the draft uniquely), one for the <strong>Note content</strong> (written in <em>Markdown</em> for formatting), one for the <em>Exhausted</em> (to mark if a note has been posted) and one for the link to a post. Initially, I filled the sheet with a bunch of ideas and drafts for my <em>Substack Notes</em>. These are short paragraphs &#8211; things like interesting quotes, quick updates, or questions for my audience. By writing them in <em>Markdown</em>, I can include italics, bold, or links as needed, since <em>Substack node</em> support basic <em>Markdown</em> formatting.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CBBv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F661a30a5-d828-4351-9697-b6df0c0976bd_594x361.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CBBv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F661a30a5-d828-4351-9697-b6df0c0976bd_594x361.png 424w, https://substackcdn.com/image/fetch/$s_!CBBv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F661a30a5-d828-4351-9697-b6df0c0976bd_594x361.png 848w, https://substackcdn.com/image/fetch/$s_!CBBv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F661a30a5-d828-4351-9697-b6df0c0976bd_594x361.png 1272w, https://substackcdn.com/image/fetch/$s_!CBBv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F661a30a5-d828-4351-9697-b6df0c0976bd_594x361.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CBBv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F661a30a5-d828-4351-9697-b6df0c0976bd_594x361.png" width="594" height="361" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/661a30a5-d828-4351-9697-b6df0c0976bd_594x361.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:361,&quot;width&quot;:594,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:20948,&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://iam.slys.dev/i/173450539?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa373db7c-9647-42ad-a1a3-87ef755cd5be_1920x1043.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_!CBBv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F661a30a5-d828-4351-9697-b6df0c0976bd_594x361.png 424w, https://substackcdn.com/image/fetch/$s_!CBBv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F661a30a5-d828-4351-9697-b6df0c0976bd_594x361.png 848w, https://substackcdn.com/image/fetch/$s_!CBBv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F661a30a5-d828-4351-9697-b6df0c0976bd_594x361.png 1272w, https://substackcdn.com/image/fetch/$s_!CBBv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F661a30a5-d828-4351-9697-b6df0c0976bd_594x361.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 role="img" 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><title></title><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>With my draft content ready, I added a <em><strong>Google Sheets</strong></em><strong> node</strong> in <em>n8n</em> and connected it after the Schedule trigger. This node uses my Google account credentials to access the sheet.</p><blockquote><p>n8n will prompt you to set up <em>Google Sheets</em> credentials if you haven&#8217;t already &#8211; it&#8217;s a one-time <em>OAuth</em> or service account setup). </p></blockquote><p>Once authenticated, I configured the <em>Google Sheets</em> node to &#8220;<em><strong>Read</strong></em>&#8221; from my spreadsheet:</p><ul><li><p>I specified the <em>Google Sheets</em> document (or picked the file from a list, since <em>n8n</em> can list your <em>Google Drive</em> files).</p></li><li><p>I set the sheet name (for example, &#8220;<em>Drafts</em>&#8221;).</p></li><li><p>I chose the operation to get all rows.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3Nq3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa1cb4f54-c5b5-4b28-a7aa-8a37a9acc13b_1194x721.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3Nq3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa1cb4f54-c5b5-4b28-a7aa-8a37a9acc13b_1194x721.png 424w, https://substackcdn.com/image/fetch/$s_!3Nq3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa1cb4f54-c5b5-4b28-a7aa-8a37a9acc13b_1194x721.png 848w, https://substackcdn.com/image/fetch/$s_!3Nq3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa1cb4f54-c5b5-4b28-a7aa-8a37a9acc13b_1194x721.png 1272w, https://substackcdn.com/image/fetch/$s_!3Nq3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa1cb4f54-c5b5-4b28-a7aa-8a37a9acc13b_1194x721.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3Nq3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa1cb4f54-c5b5-4b28-a7aa-8a37a9acc13b_1194x721.png" width="1194" height="721" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a1cb4f54-c5b5-4b28-a7aa-8a37a9acc13b_1194x721.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:721,&quot;width&quot;:1194,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:110965,&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://iam.slys.dev/i/173450539?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F366c8654-126d-4edf-b533-e2f630151ccf_1920x1043.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_!3Nq3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa1cb4f54-c5b5-4b28-a7aa-8a37a9acc13b_1194x721.png 424w, https://substackcdn.com/image/fetch/$s_!3Nq3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa1cb4f54-c5b5-4b28-a7aa-8a37a9acc13b_1194x721.png 848w, https://substackcdn.com/image/fetch/$s_!3Nq3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa1cb4f54-c5b5-4b28-a7aa-8a37a9acc13b_1194x721.png 1272w, https://substackcdn.com/image/fetch/$s_!3Nq3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa1cb4f54-c5b5-4b28-a7aa-8a37a9acc13b_1194x721.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 role="img" 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><title></title><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>When this node runs, it will fetch all the rows from my draft sheet. In <em>n8n</em>, the output of this node is a list of items (each item corresponds to one row/note, with fields for each column). So at this point in the workflow, I have an in-memory list of every draft note that&#8217;s in the <em>Google Sheet</em>.</p><p>However, I <strong>don&#8217;t want to post all of them at once</strong> &#8211; I just need one per run. Also, I want to avoid posting any note that&#8217;s already been posted before. That means I need to filter out any rows that are marked &#8220;<em>exhausted</em>&#8221; (i.e., already used). To handle that, I added a small filter in the workflow.</p><h2><strong>&#128269; Filtering out used Notes and picking a random draft</strong></h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pSjz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17f62bb6-493d-4fb3-80e0-a6765817e203_817x299.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pSjz!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17f62bb6-493d-4fb3-80e0-a6765817e203_817x299.png 424w, https://substackcdn.com/image/fetch/$s_!pSjz!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17f62bb6-493d-4fb3-80e0-a6765817e203_817x299.png 848w, https://substackcdn.com/image/fetch/$s_!pSjz!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17f62bb6-493d-4fb3-80e0-a6765817e203_817x299.png 1272w, https://substackcdn.com/image/fetch/$s_!pSjz!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17f62bb6-493d-4fb3-80e0-a6765817e203_817x299.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pSjz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17f62bb6-493d-4fb3-80e0-a6765817e203_817x299.png" width="817" height="299" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/17f62bb6-493d-4fb3-80e0-a6765817e203_817x299.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:299,&quot;width&quot;:817,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:24502,&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://iam.slys.dev/i/173450539?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7db7c567-dd0f-4175-b884-f350f29b696d_1920x1043.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_!pSjz!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17f62bb6-493d-4fb3-80e0-a6765817e203_817x299.png 424w, https://substackcdn.com/image/fetch/$s_!pSjz!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17f62bb6-493d-4fb3-80e0-a6765817e203_817x299.png 848w, https://substackcdn.com/image/fetch/$s_!pSjz!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17f62bb6-493d-4fb3-80e0-a6765817e203_817x299.png 1272w, https://substackcdn.com/image/fetch/$s_!pSjz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17f62bb6-493d-4fb3-80e0-a6765817e203_817x299.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 role="img" 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><title></title><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>After reading the rows from the sheet, I introduced an <em>Filter node</em> in <em>n8n</em> to help filter out used notes. The <em>Filter node</em> is configured to check the &#8220;<em>Exhausted</em>&#8221; field of each item. If the status is "<em>true</em>" (or whatever keyword I use to mark a used note), the <em>Filter</em> <em>node</em> will categorize that item is not to be used. I used <em>toString()</em> method to make sure <em>n8n</em> is able to compare value correctly.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!lHTd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7277666-6c52-4eaa-9635-e4d9131934d8_747x923.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lHTd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7277666-6c52-4eaa-9635-e4d9131934d8_747x923.png 424w, https://substackcdn.com/image/fetch/$s_!lHTd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7277666-6c52-4eaa-9635-e4d9131934d8_747x923.png 848w, https://substackcdn.com/image/fetch/$s_!lHTd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7277666-6c52-4eaa-9635-e4d9131934d8_747x923.png 1272w, https://substackcdn.com/image/fetch/$s_!lHTd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7277666-6c52-4eaa-9635-e4d9131934d8_747x923.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!lHTd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7277666-6c52-4eaa-9635-e4d9131934d8_747x923.png" width="747" height="923" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d7277666-6c52-4eaa-9635-e4d9131934d8_747x923.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:923,&quot;width&quot;:747,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:43423,&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://iam.slys.dev/i/173450539?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1ab3d20-9b55-47f1-85de-1989803619ee_1920x1043.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_!lHTd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7277666-6c52-4eaa-9635-e4d9131934d8_747x923.png 424w, https://substackcdn.com/image/fetch/$s_!lHTd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7277666-6c52-4eaa-9635-e4d9131934d8_747x923.png 848w, https://substackcdn.com/image/fetch/$s_!lHTd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7277666-6c52-4eaa-9635-e4d9131934d8_747x923.png 1272w, https://substackcdn.com/image/fetch/$s_!lHTd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7277666-6c52-4eaa-9635-e4d9131934d8_747x923.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 role="img" 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><title></title><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>If the status is blank or not exhausted, it goes to the true path. By connecting only the true output of this <em>Filter node</em> to the next steps, I ensure that only fresh, <strong>not-yet-posted notes</strong> continue through the workflow. In plain terms, this prunes out any note I&#8217;ve already posted before, so we don&#8217;t accidentally repeat content.</p><p>Now, assuming there&#8217;s at least one fresh note available, I typically have a subset of items ready to choose from (maybe I have 30 draft notes written in the sheet, for example). </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!BFgO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F667ecfcf-b8b3-4045-90d6-8bc68a278782_991x335.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!BFgO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F667ecfcf-b8b3-4045-90d6-8bc68a278782_991x335.png 424w, https://substackcdn.com/image/fetch/$s_!BFgO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F667ecfcf-b8b3-4045-90d6-8bc68a278782_991x335.png 848w, https://substackcdn.com/image/fetch/$s_!BFgO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F667ecfcf-b8b3-4045-90d6-8bc68a278782_991x335.png 1272w, https://substackcdn.com/image/fetch/$s_!BFgO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F667ecfcf-b8b3-4045-90d6-8bc68a278782_991x335.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!BFgO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F667ecfcf-b8b3-4045-90d6-8bc68a278782_991x335.png" width="991" height="335" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/667ecfcf-b8b3-4045-90d6-8bc68a278782_991x335.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:335,&quot;width&quot;:991,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:28616,&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://iam.slys.dev/i/173450539?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f179658-08ae-43af-9819-fba0f3cc6961_1920x1043.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_!BFgO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F667ecfcf-b8b3-4045-90d6-8bc68a278782_991x335.png 424w, https://substackcdn.com/image/fetch/$s_!BFgO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F667ecfcf-b8b3-4045-90d6-8bc68a278782_991x335.png 848w, https://substackcdn.com/image/fetch/$s_!BFgO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F667ecfcf-b8b3-4045-90d6-8bc68a278782_991x335.png 1272w, https://substackcdn.com/image/fetch/$s_!BFgO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F667ecfcf-b8b3-4045-90d6-8bc68a278782_991x335.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 role="img" 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><title></title><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>I wanted the selection to feel a bit random &#8211; I didn&#8217;t necessarily want to always post them in the same order as they appear in the sheet. To achieve this, I added an <em>Sort node</em> to do a little trick: <strong>randomize the order</strong> of the items.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3Xys!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff00c2cf2-e679-438d-aa40-e10ae3c85b79_570x920.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3Xys!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff00c2cf2-e679-438d-aa40-e10ae3c85b79_570x920.png 424w, https://substackcdn.com/image/fetch/$s_!3Xys!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff00c2cf2-e679-438d-aa40-e10ae3c85b79_570x920.png 848w, https://substackcdn.com/image/fetch/$s_!3Xys!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff00c2cf2-e679-438d-aa40-e10ae3c85b79_570x920.png 1272w, https://substackcdn.com/image/fetch/$s_!3Xys!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff00c2cf2-e679-438d-aa40-e10ae3c85b79_570x920.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3Xys!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff00c2cf2-e679-438d-aa40-e10ae3c85b79_570x920.png" width="570" height="920" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f00c2cf2-e679-438d-aa40-e10ae3c85b79_570x920.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:920,&quot;width&quot;:570,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:25567,&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://iam.slys.dev/i/173450539?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17014e0b-ce31-4e09-920a-1777a0366b17_1920x1043.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_!3Xys!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff00c2cf2-e679-438d-aa40-e10ae3c85b79_570x920.png 424w, https://substackcdn.com/image/fetch/$s_!3Xys!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff00c2cf2-e679-438d-aa40-e10ae3c85b79_570x920.png 848w, https://substackcdn.com/image/fetch/$s_!3Xys!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff00c2cf2-e679-438d-aa40-e10ae3c85b79_570x920.png 1272w, https://substackcdn.com/image/fetch/$s_!3Xys!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff00c2cf2-e679-438d-aa40-e10ae3c85b79_570x920.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 role="img" 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><title></title><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>The Sort node in <em>n8n</em> has an operation for sorting items randomly. Just needed operation set to &#8220;<em>Random</em>&#8221;. </p><p>Another step was limiting the number of items.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!43Tn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6352085e-95a4-4daf-9f2c-e28c71691c5e_1126x242.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!43Tn!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6352085e-95a4-4daf-9f2c-e28c71691c5e_1126x242.png 424w, https://substackcdn.com/image/fetch/$s_!43Tn!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6352085e-95a4-4daf-9f2c-e28c71691c5e_1126x242.png 848w, https://substackcdn.com/image/fetch/$s_!43Tn!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6352085e-95a4-4daf-9f2c-e28c71691c5e_1126x242.png 1272w, https://substackcdn.com/image/fetch/$s_!43Tn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6352085e-95a4-4daf-9f2c-e28c71691c5e_1126x242.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!43Tn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6352085e-95a4-4daf-9f2c-e28c71691c5e_1126x242.png" width="1126" height="242" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6352085e-95a4-4daf-9f2c-e28c71691c5e_1126x242.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:242,&quot;width&quot;:1126,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:27841,&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://iam.slys.dev/i/173450539?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9791d51e-1969-427c-b496-2e583d0dd08b_1920x1043.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_!43Tn!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6352085e-95a4-4daf-9f2c-e28c71691c5e_1126x242.png 424w, https://substackcdn.com/image/fetch/$s_!43Tn!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6352085e-95a4-4daf-9f2c-e28c71691c5e_1126x242.png 848w, https://substackcdn.com/image/fetch/$s_!43Tn!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6352085e-95a4-4daf-9f2c-e28c71691c5e_1126x242.png 1272w, https://substackcdn.com/image/fetch/$s_!43Tn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6352085e-95a4-4daf-9f2c-e28c71691c5e_1126x242.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>In fact, you can use the <em>Limit node</em> to limit the output. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_jVV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38236c84-a8a5-46af-ad42-4b87944d2c6e_557x924.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_jVV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38236c84-a8a5-46af-ad42-4b87944d2c6e_557x924.png 424w, https://substackcdn.com/image/fetch/$s_!_jVV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38236c84-a8a5-46af-ad42-4b87944d2c6e_557x924.png 848w, https://substackcdn.com/image/fetch/$s_!_jVV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38236c84-a8a5-46af-ad42-4b87944d2c6e_557x924.png 1272w, https://substackcdn.com/image/fetch/$s_!_jVV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38236c84-a8a5-46af-ad42-4b87944d2c6e_557x924.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_jVV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38236c84-a8a5-46af-ad42-4b87944d2c6e_557x924.png" width="557" height="924" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/38236c84-a8a5-46af-ad42-4b87944d2c6e_557x924.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:924,&quot;width&quot;:557,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:25359,&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://iam.slys.dev/i/173450539?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf772b64-4ae8-4641-afcd-f877af8a750a_1920x1043.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_!_jVV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38236c84-a8a5-46af-ad42-4b87944d2c6e_557x924.png 424w, https://substackcdn.com/image/fetch/$s_!_jVV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38236c84-a8a5-46af-ad42-4b87944d2c6e_557x924.png 848w, https://substackcdn.com/image/fetch/$s_!_jVV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38236c84-a8a5-46af-ad42-4b87944d2c6e_557x924.png 1272w, https://substackcdn.com/image/fetch/$s_!_jVV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38236c84-a8a5-46af-ad42-4b87944d2c6e_557x924.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 role="img" 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><title></title><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>I configured it to take the first 1 item. </p><p>At this point in the workflow, we&#8217;ve done the heavy lifting in terms of logic. We have one item (a note) that is fresh and randomly chosen from our <em>Google Sheet</em>. The next step is the fun part: publishing it to <em>Substack</em>!</p><div><hr></div><p><strong>&#128488;&#65039;&#128295; Want to geek out about workflow tricks, or need a hand fine-tuning your setup?</strong></p><p> Join the chat - it&#8217;s where we solve puzzles together!</p><div class="community-chat" data-attrs="{&quot;url&quot;:&quot;https://open.substack.com/pub/slys/chat?utm_source=chat_embed&quot;,&quot;subdomain&quot;:&quot;slys&quot;,&quot;pub&quot;:{&quot;id&quot;:2817779,&quot;name&quot;:&quot;slys.dev&quot;,&quot;author_name&quot;:&quot;Jakub Slys &#127894;&#65039;&quot;,&quot;author_photo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!a5_b!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d17c584-3500-4a83-9db9-f826c356ee62_2000x2000.png&quot;}}" data-component-name="CommunityChatRenderPlaceholder"></div><div><hr></div><h2><strong>&#128228; Publishing the Note to Substack</strong></h2><p>With the content ready, I connected the next node: the <em>Substack node</em> (the custom <em>n8n</em> integration I had built earlier). If you don&#8217;t have this node in your <em>n8n</em> yet, you can install it easily as a community module &#8211; in n8n&#8217;s settings, go to <em>Community Nodes</em> and search for "<em>n8n-nodes-substack</em>" and install it. Once installed, you&#8217;ll have a node that can interface with Substack&#8217;s (unofficial) API.</p><div><hr></div><p>Before using the Substack node, there&#8217;s a one-time setup for credentials. Since Substack doesn&#8217;t provide an API token, the node uses your session cookie to authenticate (basically, it acts on your behalf as if it were your browser). You can read about in the below post.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;3325c447-a29d-46b7-beba-5190c2d04500&quot;,&quot;caption&quot;:&quot;In my last post, I chronicled how I reverse-engineered Substack&#8217;s hidden API to build an unofficial javascript client. It was a deep dive into Substack&#8217;s inner workings &#8211; fun for code enthusiasts, but not exactly accessible to everyone. Ever since, I&#8217;ve been itching to make&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Substack automation with n8n: how to publish Notes automatically &#128640;&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:254824415,&quot;name&quot;:&quot;Jakub Slys &#127894;&#65039;&quot;,&quot;bio&quot;:&quot;Ever wonder how Uber matches rides &#128663; in seconds or how OpenAI &#129302; chats like a human? &#128187; Engineer @ Pega | ex-Sabre | ex-Nokia&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4d17c584-3500-4a83-9db9-f826c356ee62_2000x2000.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-08-15T13:08:12.190Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!5bth!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc9f58de-1b2e-4010-94ff-b26091d39380_1536x1024.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://iam.slys.dev/p/substack-automation-with-n8n-how&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:170924044,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:130,&quot;comment_count&quot;:53,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;slys.dev&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!9q0E!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3b67508-e73c-434b-89ae-fde2c72e8fa4_256x256.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5FeL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4828a286-6434-41f4-8bbd-7ce4ed13630e_1321x299.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5FeL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4828a286-6434-41f4-8bbd-7ce4ed13630e_1321x299.png 424w, https://substackcdn.com/image/fetch/$s_!5FeL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4828a286-6434-41f4-8bbd-7ce4ed13630e_1321x299.png 848w, https://substackcdn.com/image/fetch/$s_!5FeL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4828a286-6434-41f4-8bbd-7ce4ed13630e_1321x299.png 1272w, https://substackcdn.com/image/fetch/$s_!5FeL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4828a286-6434-41f4-8bbd-7ce4ed13630e_1321x299.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5FeL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4828a286-6434-41f4-8bbd-7ce4ed13630e_1321x299.png" width="1321" height="299" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4828a286-6434-41f4-8bbd-7ce4ed13630e_1321x299.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:299,&quot;width&quot;:1321,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:33170,&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://iam.slys.dev/i/173450539?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57e24ca0-bf38-4e91-9ba5-65f2e5b85e2e_1920x1043.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_!5FeL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4828a286-6434-41f4-8bbd-7ce4ed13630e_1321x299.png 424w, https://substackcdn.com/image/fetch/$s_!5FeL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4828a286-6434-41f4-8bbd-7ce4ed13630e_1321x299.png 848w, https://substackcdn.com/image/fetch/$s_!5FeL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4828a286-6434-41f4-8bbd-7ce4ed13630e_1321x299.png 1272w, https://substackcdn.com/image/fetch/$s_!5FeL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4828a286-6434-41f4-8bbd-7ce4ed13630e_1321x299.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Now back to the workflow: I added <em>Substack node</em> to interact with <em>Substack Notes</em>. </p><p>I configured the <em>Substack node&#8217;s</em> parameters as follows.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2edt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3df48ffd-9fc0-4aa6-acdb-72bb48a2d547_544x926.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2edt!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3df48ffd-9fc0-4aa6-acdb-72bb48a2d547_544x926.png 424w, https://substackcdn.com/image/fetch/$s_!2edt!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3df48ffd-9fc0-4aa6-acdb-72bb48a2d547_544x926.png 848w, https://substackcdn.com/image/fetch/$s_!2edt!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3df48ffd-9fc0-4aa6-acdb-72bb48a2d547_544x926.png 1272w, https://substackcdn.com/image/fetch/$s_!2edt!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3df48ffd-9fc0-4aa6-acdb-72bb48a2d547_544x926.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2edt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3df48ffd-9fc0-4aa6-acdb-72bb48a2d547_544x926.png" width="544" height="926" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3df48ffd-9fc0-4aa6-acdb-72bb48a2d547_544x926.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:926,&quot;width&quot;:544,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:60241,&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://iam.slys.dev/i/173450539?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c97437d-543a-4f48-987a-76ae23b4c1cc_1920x1043.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_!2edt!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3df48ffd-9fc0-4aa6-acdb-72bb48a2d547_544x926.png 424w, https://substackcdn.com/image/fetch/$s_!2edt!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3df48ffd-9fc0-4aa6-acdb-72bb48a2d547_544x926.png 848w, https://substackcdn.com/image/fetch/$s_!2edt!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3df48ffd-9fc0-4aa6-acdb-72bb48a2d547_544x926.png 1272w, https://substackcdn.com/image/fetch/$s_!2edt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3df48ffd-9fc0-4aa6-acdb-72bb48a2d547_544x926.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 role="img" 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><title></title><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><ul><li><p><strong>Resource</strong>: &#8220;<em>Note</em>&#8221; (meaning we are dealing with Substack Notes).</p></li><li><p><strong>Operation</strong>: &#8220;<em>Create</em>&#8221; (we want to create/post a new note).</p></li><li><p><strong>Body</strong>: here&#8217;s where I needed to put the content of the note. I didn&#8217;t type anything in manually; instead I used <em>n8n&#8217;s</em> expression editor to reference the text from the selected <em>Google Sheet</em> item. Essentially, I set the Body field to the <strong>Note content</strong> value coming from the previous node<strong>.</strong></p></li><li><p><strong>Content Type</strong>: notes&#8217; content is written in <em>Markdown</em>, I wanted to leverage from this fact to post formatted content. </p></li><li><p><strong>Link URL</strong>: link to the post.</p></li></ul><p>When everything is wired up, the <em>Substack node</em> will take that note text and publish it to my <em>Substack</em> account as a new <em>Note</em>. &#127881; Because I wrote the note in <em>Markdown</em> (in the <em>Google Sheet</em>), and <em>Substack Notes</em> support formatting, I didn&#8217;t need to modify the text at all &#8211; it could include links, bold/italic, etc., and it would appear formatted correctly on <em>Substack</em>. The <em>Substack node</em> handles sending this off to <em>Substack&#8217;s</em> servers. Under the hood, it&#8217;s making the same kind of request your browser would if you posted manually, just automated. </p><p>I remember the first time I tested this part: I ran the workflow (with a manual trigger for testing) and watched <em>n8n</em> execute each step. When it hit the <em>Substack node</em>, I held my breath &#8211; then checked my <em>Substack</em> profile&#8230; <strong>Voila!</strong> A new note had appeared, exactly as if I had posted it myself. At that moment I may have done a little happy dance &#129336;&#8205;&#9794;&#65039; &#8211; it worked!</p><h2><strong>&#9989; Marking the posted Note as &#8220;exhausted&#8221; in the sheet</strong></h2><p>The last step in the workflow is a bit of housekeeping. Remember, I don&#8217;t want to post the same note twice. So after successfully publishing a note, I need to go back to my <em>Google Sheet</em> and mark that note as used (or &#8220;<em>exhausted</em>&#8221; as I termed it). This way, the next time the workflow runs, that note will be filtered out.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fpqB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2de16d2-4869-467e-9dcf-6f278d6502c9_1580x237.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fpqB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2de16d2-4869-467e-9dcf-6f278d6502c9_1580x237.png 424w, https://substackcdn.com/image/fetch/$s_!fpqB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2de16d2-4869-467e-9dcf-6f278d6502c9_1580x237.png 848w, https://substackcdn.com/image/fetch/$s_!fpqB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2de16d2-4869-467e-9dcf-6f278d6502c9_1580x237.png 1272w, https://substackcdn.com/image/fetch/$s_!fpqB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2de16d2-4869-467e-9dcf-6f278d6502c9_1580x237.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fpqB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2de16d2-4869-467e-9dcf-6f278d6502c9_1580x237.png" width="1580" height="237" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c2de16d2-4869-467e-9dcf-6f278d6502c9_1580x237.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:237,&quot;width&quot;:1580,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:38131,&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://iam.slys.dev/i/173450539?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F98fe4424-12e2-4b79-b6c6-9f394da58687_1920x1043.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_!fpqB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2de16d2-4869-467e-9dcf-6f278d6502c9_1580x237.png 424w, https://substackcdn.com/image/fetch/$s_!fpqB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2de16d2-4869-467e-9dcf-6f278d6502c9_1580x237.png 848w, https://substackcdn.com/image/fetch/$s_!fpqB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2de16d2-4869-467e-9dcf-6f278d6502c9_1580x237.png 1272w, https://substackcdn.com/image/fetch/$s_!fpqB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc2de16d2-4869-467e-9dcf-6f278d6502c9_1580x237.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>To do this, I added <strong>another </strong><em><strong>Google Sheets</strong></em><strong> node</strong> at the end of the flow, connected after the <em>Substack node</em>. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7bP0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F75f12592-7804-43c7-b762-c7fddc86ae34_1191x928.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7bP0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F75f12592-7804-43c7-b762-c7fddc86ae34_1191x928.png 424w, https://substackcdn.com/image/fetch/$s_!7bP0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F75f12592-7804-43c7-b762-c7fddc86ae34_1191x928.png 848w, https://substackcdn.com/image/fetch/$s_!7bP0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F75f12592-7804-43c7-b762-c7fddc86ae34_1191x928.png 1272w, https://substackcdn.com/image/fetch/$s_!7bP0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F75f12592-7804-43c7-b762-c7fddc86ae34_1191x928.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7bP0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F75f12592-7804-43c7-b762-c7fddc86ae34_1191x928.png" width="1191" height="928" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/75f12592-7804-43c7-b762-c7fddc86ae34_1191x928.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:928,&quot;width&quot;:1191,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:214353,&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://iam.slys.dev/i/173450539?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1fae148-28d7-424f-9a99-8d6192dd70fa_1920x1043.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_!7bP0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F75f12592-7804-43c7-b762-c7fddc86ae34_1191x928.png 424w, https://substackcdn.com/image/fetch/$s_!7bP0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F75f12592-7804-43c7-b762-c7fddc86ae34_1191x928.png 848w, https://substackcdn.com/image/fetch/$s_!7bP0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F75f12592-7804-43c7-b762-c7fddc86ae34_1191x928.png 1272w, https://substackcdn.com/image/fetch/$s_!7bP0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F75f12592-7804-43c7-b762-c7fddc86ae34_1191x928.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 role="img" 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><title></title><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>This one is configured to Update a row in the spreadsheet:</p><ul><li><p>I set the operation to &#8220;<em>Append</em> or <em>Update Row</em>&#8221;.</p></li><li><p>For the <strong>Key</strong> to identify which row to update, I used a unique value that identifies the note. In my case, since the note already has unique ID, I could use that.</p></li><li><p>I dynamically set the key value to match the note we just published. The ID is retrieved from the Limit step to match the ID from the <em>Google Sheet</em> item. </p></li></ul><blockquote><p>NOTE: The ID from the <em>Substack node</em> output is the note ID assigned by the <em>Substack</em> server. It does not match the ID from the <em>Google Sheet</em> item.</p></blockquote><ul><li><p>Finally, I set the field <strong>Status</strong> (the &#8220;<em>Exhausted</em>&#8221; column) to "<em>TRUE</em>" (or you could use &#8220;<em>yes</em>&#8221;, &#8220;<em>posted</em>&#8221;, a date timestamp, whatever you prefer to indicate it&#8217;s been used).</p></li></ul><p>When this runs, the <em>Google Sheets</em> node will go and update that specific row in the sheet to mark it. <em>n8n&#8217;s</em> <em>Google Sheets</em> integration takes care of finding the row and updating the cell. After this, our workflow cycle is complete!</p><p>Now, the next time the Schedule trigger fires, the Google Sheets read node will fetch all rows, the IF filter will drop the ones where Status is &#8220;<em>exhausted</em>&#8221; (including the one we just posted), and a new random note will be chosen from the remaining drafts. Rinse and repeat automatically.</p><p>By the way, I also considered: what if the sheet becomes empty or all notes are exhausted? In that case, the workflow would end up with nothing to post. For now, I just keep an eye on my drafts and add new ones as I use them up (<em>n8n</em> could send me an alert when I&#8217;m running low, but I haven&#8217;t gotten that fancy yet). For a beginner setup, it&#8217;s easiest to just ensure you refill your <em>Google Sheet</em> with new notes periodically. You could even automate pulling in ideas from elsewhere, but that&#8217;s a story for another time!</p><h1>&#128204; <strong>Recap: how the automated notes system works</strong></h1><p>To summarize, here are the key pieces of the <em>Substack Notes</em> scheduling system I built.</p><p><strong>Schedule trigger node.</strong> I used <em>n8n&#8217;s</em> <em>Schedule trigger</em> to run the workflow on a regular schedule (every few hours in my case). This ensures notes get posted consistently without my intervention.</p><p><strong>Google Sheets as Content Storage.</strong> I keep all my draft note content in a <em>Google Sheet</em>. This makes it easy to add/edit notes. The n8n <em>Google Sheets node</em> reads all the draft notes each time, and later updates the sheet to mark which note was posted.</p><p><strong>Filtering and Random Selection.</strong> The workflow filters out any notes that have already been posted (using an <em>Filter node</em> on a status column). Then it randomly selects one note from the remaining drafts to post. We achieved randomness by using the <em>Sort node</em> to shuffle and <em>Limit node</em> to pick one item.</p><p><strong>Substack Publishing via n8n.</strong> Thanks to a custom <em>Substack node</em> (community integration), the workflow can log into my <em>Substack</em> and create a new <em>Note</em> with the chosen content. No manual posting needed &#8211; it&#8217;s all automated through the <em>Substack</em> API behind the scenes.</p><p><strong>Mark as Posted.</strong> After a successful post, the workflow updates the <em>Google Sheet</em>, marking that note as used (&#8220;<em>exhausted</em>&#8221;). This prevents duplicates and keeps the system going smoothly.</p><p>In practice, this means I can <strong>batch write a bunch of notes in one sitting</strong>, load them into the sheet, and then go about my week while <em>n8n</em> handles the posting schedule. It&#8217;s incredibly satisfying to see a note go live and realize, &#8220;<em>Hey, I didn&#8217;t have to do anything just now &#8211; my robot assistant did it for me!</em>&#8221; &#128516;</p><p>I hope this walkthrough inspires you to try automating your own workflows. If you&#8217;re a beginner, don&#8217;t worry &#8211; tools like <em>n8n</em> are very visual and newbie-friendly. You don&#8217;t need to code (<em>I didn&#8217;t write a single line of code for this workflow!</em>). Just drag, drop, and configure nodes with your credentials and logic. And remember, once you set it up, <strong>your content can be on autopilot</strong>. Whether it&#8217;s <em>Substack</em> <em>Notes</em>, tweets, or any other daily post, you can adapt this approach to save time and hassle.</p><div><hr></div><p><strong>&#128236;&#128640; Like this walkthrough?</strong> </p><p>Subscribe now and get more automation guides straight to your inbox - no manual refreshing needed!</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://iam.slys.dev/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://iam.slys.dev/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><p><strong>Final thought.</strong> This little project started with me being forgetful and lazy about daily posts, and it turned into a reliable system that runs in the background. It&#8217;s a great feeling to reclaim that mental space. Now I can focus more on <em>writing new content</em>, knowing that <em>n8n</em> and a <em>Google Sheet</em> have my back for the posting part. If you have repetitive tasks in your life (especially around content publishing), give automation a shot &#8211; you might wonder how you lived without it!</p><p>Happy automating, and thanks for reading my story about building a <em>Substack Notes</em> scheduler. Feel free to ask any questions or share your own automation ideas. Here&#8217;s to working smarter and freeing up time for the fun stuff! &#128640;</p><div><hr></div><p><strong>&#128230;&#9889; Want to skip the setup and dive right in?</strong> </p><p>Grab my exported workflow JSON below - just copy-paste it into your own n8n instance and you&#8217;re ready to roll!</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;727d4708-0ff3-4acb-8e75-01a1f99da1c8&quot;,&quot;caption&quot;:&quot;&#128230;&#9889; Want to skip the setup and dive right in?&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Substack Notes Scheduler (JSON)&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:254824415,&quot;name&quot;:&quot;Jakub Slys &#127894;&#65039;&quot;,&quot;bio&quot;:&quot;Ever wonder how Uber matches rides &#128663; in seconds or how OpenAI &#129302; chats like a human? &#128187; Engineer @ Pega | ex-Sabre | ex-Nokia&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4d17c584-3500-4a83-9db9-f826c356ee62_2000x2000.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-09-23T13:58:40.812Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!Nbiy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffde38c4b-18d6-420f-a9af-1597ff568b35_1536x1024.jpeg&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://iam.slys.dev/p/substack-notes-scheduler-json&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:174341594,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:3,&quot;comment_count&quot;:0,&quot;publication_id&quot;:2817779,&quot;publication_name&quot;:&quot;slys.dev&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!9q0E!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3b67508-e73c-434b-89ae-fde2c72e8fa4_256x256.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p><a href="https://zapier.com/">zapier.com</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p><a href="https://n8n.io/">n8n: Flexible AI workflow automation for technical teams</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p><a href="https://workspace.google.com/products/sheets/">Google Sheets: Online, collaborative spreadsheets</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-4" href="#footnote-anchor-4" class="footnote-number" contenteditable="false" target="_self">4</a><div class="footnote-content"><p><a href="https://support.substack.com/hc/en-us/articles/14564821756308-Getting-started-on-Substack-Notes">Getting started on Substack Notes</a></p><p></p></div></div>]]></content:encoded></item></channel></rss>