<?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[BinaryBox]]></title><description><![CDATA[BinaryBox is where coders level up to engineers. I share practical insights, mental models, and real-world stories that help you think beyond code, design better solutions, and grow into a problem-solving powerhouse.]]></description><link>https://www.binarybox.org</link><image><url>https://substackcdn.com/image/fetch/$s_!nQ1g!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5439f3e3-02d6-4fcb-916e-c999f65d4c56_300x300.png</url><title>BinaryBox</title><link>https://www.binarybox.org</link></image><generator>Substack</generator><lastBuildDate>Sat, 04 Apr 2026 09:41:34 GMT</lastBuildDate><atom:link href="https://www.binarybox.org/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Ashok Vishwakarma]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[binarybox@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[binarybox@substack.com]]></itunes:email><itunes:name><![CDATA[Ashok Vishwakarma]]></itunes:name></itunes:owner><itunes:author><![CDATA[Ashok Vishwakarma]]></itunes:author><googleplay:owner><![CDATA[binarybox@substack.com]]></googleplay:owner><googleplay:email><![CDATA[binarybox@substack.com]]></googleplay:email><googleplay:author><![CDATA[Ashok Vishwakarma]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[The $20/$200 AI Subscription is going to be Dead?]]></title><description><![CDATA[They priced access to massive supercomputers like a Spotify subscription. You paid $20 or $200 a month, and in exchange, you got an all-you-can-eat buffet of compute power.]]></description><link>https://www.binarybox.org/p/the-20200-ai-subscription-is-going</link><guid isPermaLink="false">https://www.binarybox.org/p/the-20200-ai-subscription-is-going</guid><dc:creator><![CDATA[Ashok Vishwakarma]]></dc:creator><pubDate>Thu, 02 Apr 2026 06:02:25 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Kwhi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8dfc557-d52f-4bb7-b801-4fc425dba879_1280x1560.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>For two years, the industry sold us the idea that frontier AI was just another consumer utility. They priced access to massive supercomputers like a Spotify subscription. You paid $20 or $200 a month, and in exchange, you got an all-you-can-eat buffet of compute power.</p><p>But by early 2026, the physical cost of running these models caught up with the business reality.</p><p>Look at the events of the last quarter. OpenAI shut down Sora and backed out of their Disney partnership. Microsoft is tightening its cloud budget. And a leaked internal dashboard shared by <strong><a href="https://www.linkedin.com/company/the-signal-ai/posts">The Signal</a></strong> from Anthropic showed just how unsustainable the generative AI business model is right now.</p><p>We aren&#8217;t entering an era of unlimited personal AI. We&#8217;re actually going back to the 1970s model, the era of the IBM Mainframe. The hallucination seems officially over &#128578;</p><h2>AI isn&#8217;t a SaaS</h2><p>Software-as-a-Service (SaaS) is a great business model because the marginal cost of serving one more user is effectively zero.</p><p>AI inference isn&#8217;t SaaS. It scales linearly. Every prompt requires physical hardware to do work.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Kwhi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8dfc557-d52f-4bb7-b801-4fc425dba879_1280x1560.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Kwhi!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8dfc557-d52f-4bb7-b801-4fc425dba879_1280x1560.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Kwhi!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8dfc557-d52f-4bb7-b801-4fc425dba879_1280x1560.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Kwhi!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8dfc557-d52f-4bb7-b801-4fc425dba879_1280x1560.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Kwhi!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8dfc557-d52f-4bb7-b801-4fc425dba879_1280x1560.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Kwhi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8dfc557-d52f-4bb7-b801-4fc425dba879_1280x1560.jpeg" width="1280" height="1560" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d8dfc557-d52f-4bb7-b801-4fc425dba879_1280x1560.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1560,&quot;width&quot;:1280,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:220436,&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://www.binarybox.org/i/192891847?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8dfc557-d52f-4bb7-b801-4fc425dba879_1280x1560.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_!Kwhi!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8dfc557-d52f-4bb7-b801-4fc425dba879_1280x1560.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Kwhi!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8dfc557-d52f-4bb7-b801-4fc425dba879_1280x1560.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Kwhi!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8dfc557-d52f-4bb7-b801-4fc425dba879_1280x1560.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Kwhi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd8dfc557-d52f-4bb7-b801-4fc425dba879_1280x1560.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><figcaption class="image-caption">From <strong><a href="https://www.linkedin.com/company/the-signal-ai/posts">The Signal</a></strong> </figcaption></figure></div><p>To understand why the flat-rate AI subscription is failing, look at the leaked Anthropic dashboard. An enterprise power user on a $200/month &#8220;Pro&#8221; tier ran an autonomous coding loop. In 23 days, that single user consumed 1.1 billion tokens and triggered 9,221 sub-agent tasks.</p><p>The actual compute cost of running those inferences on Anthropic&#8217;s GPU clusters was $27,000. Anthropic took a 135x loss on a single customer in less than a month. </p><p>Analyzing a 100-page PDF or running an autonomous agent isn&#8217;t a simple database query. It requires firing up clusters of GPUs and executing billions of operations. You can&#8217;t sell that kind of compute for a flat fee and hope to make it up in volume. Volume is exactly what causes the losses.</p><h3>The Death of Sora</h3><p>If you want proof that the subsidy is over, look at Sora.</p><p>OpenAI killed their flagship video generation model less than six months after its public launch. The tech press talked about &#8220;safety concerns&#8221; and &#8220;copyright,&#8221; but the reality was the Cost of Goods Sold (COGS).</p><p>Generating 60 frames per second of photorealistic video requires massive compute. Keeping the Sora clusters running for 500,000 active users burned an estimated $1 million a day in electricity and GPU depreciation.</p><p>They tried to pivot to the enterprise by signing a $1 billion partnership with Disney. But Disney realized that offloading their rendering pipeline to OpenAI&#8217;s servers was actually more expensive than doing it in-house. The unit economics didn&#8217;t make sense, so the servers were shut down.</p><h3>OpenAI&#8217;s &#8220;Risk Factor&#8221;</h3><p>The cloud providers have woken up. For years, Microsoft subsidized OpenAI&#8217;s compute to gain market share. That era of cheap infrastructure is over.</p><p>In a recent financial disclosure, OpenAI explicitly listed their reliance on Microsoft Azure&#8217;s compute pricing as a &#8220;Risk Factor.&#8221; </p><p>Wall Street is demanding a return on the billions poured into data centers. Investors are forcing AI labs to drop unprofitable consumer tools and focus entirely on enterprise contracts that actually pay the bills.</p><h2>Edge vs. Mainframe</h2><p>To fix the broken math, the AI market is splitting into two distinct tiers. </p><p>The middle ground which is $200/month frontier web app is disappearing.</p><h3>Tier 1: The Consumer Edge</h3><p>Consumers will get smaller, 8-billion parameter models running locally on their phones and laptops (Apple Silicon, Snapdragon NPUs etc).</p><p>These models are good enough for basic tasks like grammar correction and summarizing emails, but they aren&#8217;t capable of deep reasoning. </p><p>Why the shift? </p><p>Because by pushing the model to the edge, companies offload the cost of the compute and electricity directly onto the user&#8217;s battery. It is the only way the consumer unit economics work.</p><h3>Tier 2: The AI Mainframe (Enterprise)</h3><p>True frontier AI, massive models capable of deep, autonomous workflows will become bespoke enterprise tools.</p><p>These won&#8217;t be accessible via a casual web interface. </p><p>They will be sold via multi-million-dollar B2B contracts to pharmaceutical companies running protein simulations, and quant hedge funds executing trading logic. </p><p>They are the only businesses with gross margins high enough to afford the true, unsubsidized cost of compute.</p><div><hr></div><h2>Conclusion</h2><p>The idea that a solo developer in a garage will have the exact same compute power as the CTO of JPMorgan isn&#8217;t realistic. </p><p>The physics of data centers dictate otherwise.</p><p>As a Software Architect, you need to plan defensively. Relying on cloud providers to subsidize your application&#8217;s heavy reasoning is a risk.</p><p>Build your systems around cheap, local, open-source models for the basic plumbing such as routing, classification, and simple tasks. </p><p>Treat frontier API calls as an expensive, highly constrained physical resource. </p><p>Use them only when absolutely necessary and plan for AI like heavy industrial equipment. </p><p>The era of cheap, subsidized compute is over.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.binarybox.org/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">Thanks for reading BinaryBox! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[A ₹500 ($5) course won't make you an AI Engineer]]></title><description><![CDATA[They claim that AI is replacing software engineers tomorrow, and if you don&#8217;t buy their &#8220;AI Mastery Guide&#8221; today, your career is over before it begins.]]></description><link>https://www.binarybox.org/p/a-500-5-course-wont-make-you-an-ai</link><guid isPermaLink="false">https://www.binarybox.org/p/a-500-5-course-wont-make-you-an-ai</guid><dc:creator><![CDATA[Ashok Vishwakarma]]></dc:creator><pubDate>Tue, 31 Mar 2026 12:03:53 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!y-Gm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d3ed674-2cd5-40b7-8fee-5be0b4aebed3_1536x768.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_!y-Gm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d3ed674-2cd5-40b7-8fee-5be0b4aebed3_1536x768.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!y-Gm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d3ed674-2cd5-40b7-8fee-5be0b4aebed3_1536x768.png 424w, https://substackcdn.com/image/fetch/$s_!y-Gm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d3ed674-2cd5-40b7-8fee-5be0b4aebed3_1536x768.png 848w, https://substackcdn.com/image/fetch/$s_!y-Gm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d3ed674-2cd5-40b7-8fee-5be0b4aebed3_1536x768.png 1272w, https://substackcdn.com/image/fetch/$s_!y-Gm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d3ed674-2cd5-40b7-8fee-5be0b4aebed3_1536x768.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!y-Gm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d3ed674-2cd5-40b7-8fee-5be0b4aebed3_1536x768.png" width="1456" height="728" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4d3ed674-2cd5-40b7-8fee-5be0b4aebed3_1536x768.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:728,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1947599,&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://www.binarybox.org/i/191716866?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d3ed674-2cd5-40b7-8fee-5be0b4aebed3_1536x768.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_!y-Gm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d3ed674-2cd5-40b7-8fee-5be0b4aebed3_1536x768.png 424w, https://substackcdn.com/image/fetch/$s_!y-Gm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d3ed674-2cd5-40b7-8fee-5be0b4aebed3_1536x768.png 848w, https://substackcdn.com/image/fetch/$s_!y-Gm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d3ed674-2cd5-40b7-8fee-5be0b4aebed3_1536x768.png 1272w, https://substackcdn.com/image/fetch/$s_!y-Gm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d3ed674-2cd5-40b7-8fee-5be0b4aebed3_1536x768.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>Take a breath.</p><p>I know what your LinkedIn and Twitter feeds look like right now. </p><p>Every time you open your phone, an influencer in a rented sports car or a sleek home office is screaming at you. </p><p>They claim that AI is replacing software engineers tomorrow, and if you don&#8217;t buy their <em><strong>&#8220;AI Mastery Guide&#8221;</strong></em> today, your career is over before it begins.</p><p>I see the panic in computer science cohorts and junior developers. It is entirely valid. </p><p>But you need to understand that this anxiety is not a natural reaction to the tech market. It is a manufactured emotion, meticulously engineered by marketers to make you feel inadequate so you will open your wallet.</p><p>In any gold rush, the people who actually get rich are the ones selling the shovels. Today&#8217;s &#8220;AI Influencers&#8221; are selling cheap, plastic shovels to desperate, anxious students.</p><p>Let&#8217;s tear down their selling tactics like an architecture.</p><h2>The Scam</h2><p>If you want to be an engineer, you need to learn how to reverse-engineer systems. </p><p>Let&#8217;s look at the system design of the influencer business model.</p><p>When you see an ad for a &#8220;Master ChatGPT in 30 Days&#8221; course priced at &#8377;500 or $5, you think you are buying an educational product. </p><p>You are not. You are participating in a Customer Acquisition Cost (CAC) mechanism.</p><p>That &#8377;500 course is just the entry point to a sales funnel. The content inside is nothing but regurgitated Twitter threads, repackaged into a PDF to create artificial complexity. </p><p>It is designed to give you a dopamine hit of &#8220;productivity&#8221; while making you feel like you are still missing the <em>real</em> secret.</p><p>Then, the trap springs. Once you finish the cheap course, the email sequence begins. </p><p>They tell you that to <em>actually</em> secure a six-figure job, you need to join their exclusive &#8220;AI Mastermind&#8221; or buy the advanced bootcamp for &#8377;50,000.</p><p>You are being farmed for your attention and your anxiety.</p><h2>The Delusion</h2><p>The core lie holding this entire grift together is the concept of the &#8220;Prompt Engineer.&#8221;</p><p>Let me give you the hard truth</p><p>Prompt Engineering is not a sustainable technical career. </p><p>A prompt is simply a natural language API call. You are no more an &#8220;engineer&#8221; for typing instructions into ChatGPT than you are a &#8220;Search Engineer&#8221; for typing queries into Google.</p><p>More importantly, it is a rapidly depreciating asset.</p><p>Two years ago, getting an LLM to output a specific JSON format required paragraphs of complex &#8220;jailbreak&#8221; constraints and magical phrasing. </p><p>Today, frontier models like Claude 3.5 Sonnet, GPT-4o, and Gemini 1.5 Pro natively understand intent, reason through logic, and output strict JSON out of the box.</p><p>The models are getting smarter at interpreting human ambiguity. As the compilers (the LLMs) get better at understanding natural language, the need for complex, esoteric &#8220;prompts&#8221; disappears. </p><p>Buying a course on prompting is investing your limited time and money into a dying skill.</p><h2>The Trap</h2><p>Part of the illusion relies heavily on visual spectacle. </p><p>The influencer will open a video by shouting, </p><p><em><strong>&#8220;I just generated a 50-page PowerPoint, a PDF marketing brochure, and 12 photorealistic images in under three minutes using these SECRET tools!&#8221;</strong></em></p><p>They will show you a curated list of glossy AI web apps or tools that automatically build slide decks, generate stock photos, or format PDFs. </p><p>They will try to convince you that knowing which button to click on these websites is a highly monetizable, technical skill.</p><p>Let me be brutally clear.</p><p>Using a SaaS wrapper to generate a PDF makes you an <em>end-user</em>, not an engineer.</p><p>You are not building software. You are consuming it. </p><p>Knowing how to type a prompt into an image generator or a presentation-maker is equivalent to claiming you are a Database Architect because you know how to sort a column in Microsoft Excel. </p><p>It is a neat productivity trick for a marketing manager, but it has absolutely zero engineering value. </p><p>When you buy a course to learn these tools, you are paying for a glorified software tutorial, not an engineering curriculum.</p><h2>The Real AI Engineering</h2><p>Contrast the influencer fantasy with the brutal reality of what the industry actually pays for.</p><p>Companies do not pay AI Engineers $150,000 a year to type clever sentences into a web interface or generate a pretty slide deck.</p><p>They pay engineers to build resilient, scalable systems around non-deterministic intelligence.</p><p>Real AI engineering is systems engineering. It is building deterministic RAG (Retrieval-Augmented Generation) pipelines. It is managing the severe latency of vector databases. It is calculating the unit economics of token costs versus API throughput.</p><p>An actual AI Engineer spends their day setting up strict guardrails to catch LLM hallucinations before they reach a customer. </p><p>They write middleware to mask Personally Identifiable Information (PII) before it hits a third-party API. </p><p>They write exponential backoff algorithms to handle <code>502 Bad Gateway</code> errors and <code>429 Too Many Requests</code> rate limits from OpenAI. </p><p>They build intelligent chunking strategies to fit a massive PDF into a 100k context window without destroying the semantic meaning.</p><p>If a course does not teach you how to handle network failures, rate limits, or context window chunking, it is not an AI engineering course. </p><p>It is a typing class.</p><h2>Where you should learn?</h2><p>So, where do you actually go to learn? </p><p>You ignore the influencers and you go to the raw, unpolished sources. </p><p>Here is your actual roadmap, and it is almost entirely free.</p><h3>The Math &amp; Mechanics</h3><p>Go to YouTube and search for <strong><a href="https://www.youtube.com/watch?v=VMj-3S1tku0&amp;list=PLAqhIrjkxbuWI23v9cThsA9GvCAUhRvKZ">Andrej Karpathy&#8217;s </a></strong><em><strong><a href="https://www.youtube.com/watch?v=VMj-3S1tku0&amp;list=PLAqhIrjkxbuWI23v9cThsA9GvCAUhRvKZ">&#8220;Neural Networks: Zero to Hero&#8221;</a></strong></em> series. <strong><a href="https://en.wikipedia.org/wiki/Andrej_Karpathy">Karpathy</a></strong> was a founding member of OpenAI and the Director of AI at Tesla. </p><p>He will teach you how to build a neural network from scratch using Python. </p><p>Understanding the underlying calculus and matrix multiplication is infinitely more valuable than memorizing a prompt template.</p><h3>The Applied Systems</h3><p>Stop buying courses and start reading official documentation. </p><p>Take <strong><a href="https://grow.google/ai-coursera">Grow with Google AI Lessons</a></strong>.</p><p>Read the <strong><a href="https://platform.claude.com/docs/en/home">Anthropic documentation</a></strong>. </p><p>Read the <strong><a href="https://developers.openai.com/cookbook">OpenAI Cookbooks</a></strong>. </p><p>If you need structured courses, take <strong><a href="https://www.coursera.org/instructor/andrewng">Andrew Ng&#8217;s</a></strong> DeepLearning AI classes. </p><p>They are built by actual AI researchers, not Twitter marketers.</p><h3>The Framework</h3><p>Want to build AI apps? </p><p>Go read the raw GitHub documentation for LangChain, LlamaIndex, or Hugging Face. </p><p>Build a simple Python script that takes a local text file, converts it into embeddings, stores it in a local ChromaDB, and queries it. </p><p>You will learn more in one weekend of fighting Python dependency errors than in a year of watching influencer videos.</p><div><hr></div><h2>Conclusion</h2><p>True technical leverage does not live behind a paywall on an Instagram ad. </p><p>It lives in your ability to sit in a quiet room, read difficult technical documentation, and build things that break until you figure out how to fix them.</p><p>A career in software engineering is a 40-year marathon. </p><p>Technologies will rise and fall. Frameworks will die. </p><p>Do not let marketers rush you into buying plastic shovels.</p><p>Ignore the noise. Protect your wallet. Focus on the fundamentals.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.binarybox.org/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">Thanks for reading BinaryBox! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p>]]></content:encoded></item><item><title><![CDATA[Thought - Why Token Costs will Bankrupt your LLM Wrapper]]></title><description><![CDATA[If your COGS scales perfectly linearly with every single user click, you do not have a software business. You have a subsidized consulting firm.]]></description><link>https://www.binarybox.org/p/thought-why-token-costs-will-bankrupt</link><guid isPermaLink="false">https://www.binarybox.org/p/thought-why-token-costs-will-bankrupt</guid><dc:creator><![CDATA[Ashok Vishwakarma]]></dc:creator><pubDate>Thu, 26 Mar 2026 06:00:40 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Vqel!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69c8cb96-c797-4d10-94f0-213c6daa26c9_1400x723.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_!Vqel!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69c8cb96-c797-4d10-94f0-213c6daa26c9_1400x723.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Vqel!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69c8cb96-c797-4d10-94f0-213c6daa26c9_1400x723.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Vqel!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69c8cb96-c797-4d10-94f0-213c6daa26c9_1400x723.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Vqel!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69c8cb96-c797-4d10-94f0-213c6daa26c9_1400x723.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Vqel!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69c8cb96-c797-4d10-94f0-213c6daa26c9_1400x723.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Vqel!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69c8cb96-c797-4d10-94f0-213c6daa26c9_1400x723.jpeg" width="1400" height="723" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69c8cb96-c797-4d10-94f0-213c6daa26c9_1400x723.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:723,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:155461,&quot;alt&quot;:&quot;Token by Token: Mastering AI Cost Optimization | by Pradeep Kumar  Muthukamatchi | Data Science Collective | Medium&quot;,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Token by Token: Mastering AI Cost Optimization | by Pradeep Kumar  Muthukamatchi | Data Science Collective | Medium" title="Token by Token: Mastering AI Cost Optimization | by Pradeep Kumar  Muthukamatchi | Data Science Collective | Medium" srcset="https://substackcdn.com/image/fetch/$s_!Vqel!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69c8cb96-c797-4d10-94f0-213c6daa26c9_1400x723.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Vqel!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69c8cb96-c797-4d10-94f0-213c6daa26c9_1400x723.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Vqel!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69c8cb96-c797-4d10-94f0-213c6daa26c9_1400x723.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Vqel!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69c8cb96-c797-4d10-94f0-213c6daa26c9_1400x723.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>Last month, I was brought in to consult for a generative AI startup that had just closed a massive Seed round. They had built an &#8220;AI Customer Success Agent&#8221; that looked incredible in staging.</p><p>Then I opened their Anthropic billing dashboard.</p><p>Their Cost of Goods Sold (COGS) wasn&#8217;t just high. It was terminal. Every time a user asked their bot a question, the company lost money. </p><p>When I tore down their architecture to find the leak, I realized they hadn&#8217;t actually built a software company. They had built an unoptimized API proxy.</p><p>And this is not an isolated incident. </p><p>Look at the startup graveyard from the last two years. The AI Copywriter. The AI PDF Chatbot. The AI Email Assistant. They launched to deafening hype, dominated Product Hunt, and convinced investors they had cracked a new market.</p><p>Twelve months later, they were quietly shuttered or sold for parts.</p><p>Their entire product architecture consisted of prepending a system prompt to a user input and piping it directly to an LLM provider. They had no defensible moat, and their gross margins were systematically eaten alive by the underlying compute provider.</p><h2>The Maths of Margin Erosion</h2><p>Software-as-a-Service (SaaS) valuations are predicated on 80 percent gross margins and a near-zero marginal cost of replication. </p><p>If your COGS scales perfectly linearly with every single user click, you do not have a software business. You have a subsidized consulting firm.</p><h3>The RAG Trap</h3><p>Let&#8217;s examine the exact architecture that was killing my client. A standard enterprise RAG (Retrieval-Augmented Generation) implementation. You deploy a customer support bot handling a modest 10,000 conversations a day.</p><p>You write a dense, 2,000-token system prompt detailing the company&#8217;s tone and rules. Every time a user asks a question, your vector database retrieves 5,000 tokens of documentation context. Before the LLM generates a single word, your baseline payload is 7,000 input tokens.</p><p>At premium model pricing (roughly $10 to $15 per million input tokens for models like Claude 3 Opus or GPT-4), that single interaction costs about $0.10 just to read the prompt. Multiply that by 10,000 conversations, factoring in average multi-turn context window inflation, and you are burning <strong>$1,500+</strong> a day.</p><p>You are bleeding <strong>$500,000</strong> a year purely on input tokens before factoring in output costs, vector database hosting, or salaries.</p><h3>The Output Multiplier</h3><p>The input tax is just the entry fee. The output tax is where margins actually die.</p><p>Generating tokens requires significantly more compute than reading them. Providers charge 3x to 5x more for output tokens. If your bot generates a helpful 500-word response, that single output costs another $0.015.</p><p>Users do not ask one question; they iterate. A four-message conversation easily compounds to 30,000 total tokens processed. You are paying a premium cloud tax on every single syllable your system outputs, 24 hours a day.</p><h2>The Latency Tax</h2><p>Financial bleed is only the first failure mode. The second is Time to First Token (TTFT).</p><h3>TTFT</h3><p>TTFT is the ultimate metric in AI architecture. When you wire your frontend directly to an external LLM provider, you surrender total control of your application&#8217;s physics.</p><p>You inherit their network round-trips. You inherit their TLS handshakes. You inherit their peak-hour queue delays. You are at the mercy of raw 2-to-5-second inference times.</p><p>Human beings abandon interfaces that take more than 400 milliseconds to react. If your application takes five seconds to stream the first word because <code>us-east-1</code> is saturated, your users will leave.</p><h3>The Streaming Band-Aid</h3><p>Many developers try to hide this latency by streaming tokens to the UI. This is a visual band-aid, not an architectural fix.</p><p>Streaming gives the illusion of speed, but it does not change the physical time it takes to complete the task. </p><p>You cannot out-prompt the speed of light. </p><p>Prompt engineering cannot fix an overloaded cloud endpoint. If a backend task requires parsing JSON from an LLM response before executing a database query, streaming is useless. </p><p>You are simply blocked for five seconds.</p><h2>The Self-Hosting Fallacy</h2><p>Faced with massive API bills and latency spikes, engineering teams typically experience a knee-jerk reaction</p><p><em><strong>&#8220;Our API bill is too high. Let&#8217;s buy an H100 and host Llama 3 ourselves.&#8221;</strong></em></p><p>This is an ego trip disguised as a financial strategy.</p><h3>The Silicon Math</h3><p>Generating a million tokens on a hosted, heavily optimized API endpoint costs pennies for smaller models. Renting a single A100 or H100 GPU node costs upwards of $80 to $150 a day.</p><p>Because user traffic is spiky and unpredictable, that expensive silicon will sit completely idle 80 percent of the time. </p><p>You are paying for maximum capacity, but only utilizing a fraction of it.</p><h3>The DevOps Nightmare</h3><p>Running LLMs in production is not like running a Node.js server. It is a grueling battle with KV cache memory fragmentation, continuous batching algorithms, and CUDA out-of-memory crashes.</p><p>To keep a self-hosted model running efficiently, you need specialized AI infrastructure engineers. Those engineers cost <strong>$250,000</strong> a year.</p><p>Unless you process tens of millions of tokens daily at a perfectly consistent utilization rate, or you have strict air-gapped compliance requirements, self-hosting will bankrupt you faster than using LLM APIs. </p><p>You trade variable API costs for massive fixed CapEx and severe operational friction.</p><h2>Architecting the Defensive Moat</h2><p>To survive the LLM API tax, architects must build a ruthless abstraction layer between their application and the model provider. </p><p>You need an AI Gateway.</p><h3>Tactic 1: Semantic Caching</h3><p>Users ask the exact same questions constantly. You should not pay Anthropic 1,000 times a day to answer <em><strong>&#8220;What is your refund policy?&#8221;</strong></em></p><p>Instead, pass the user&#8217;s query through a cheap, sub-millisecond embedding model. Store that vector in a Redis cache alongside the LLM&#8217;s final generated response. </p><p>When the next user asks <em><strong>&#8220;How do I get my money back?&#8221;,</strong></em> perform a cosine similarity search.</p><p>If the mathematical match exceeds a 0.95 threshold, serve the cached string instantly. Your compute cost drops to $0. </p><p>Your TTFT drops to 50 milliseconds.</p><h3>Tactic 2: Intelligent Routing (The Cascade)</h3><p>Stop using premium frontier models for everything. A massive percentage of application logic involves basic classification, sentiment analysis, or summarization.</p><p>Your gateway should route trivial tasks to ultra-cheap, high-speed models like Gemini Flash, Llama 3 8B, or Claude Haiku. </p><p>Reserve the expensive, heavy reasoning models strictly for complex escalation paths. Implement a cascade, try the cheap model first, and only trigger the expensive model if the output fails a deterministic validation check.</p><h3>Tactic 3: Context Pruning</h3><p>Stop treating the LLM context window as a dumping ground. </p><p>Throwing 50 pages of PDF text into an API call because &#8220;the model supports 1M tokens&#8221; is financial suicide.</p><p>Implement strict context pruning. </p><p>Use a fast Cross-Encoder to re-rank your vector search results. Strip out boilerplate text, HTML tags, and redundant paragraphs before assembling the final prompt. </p><p>Sending exactly 800 highly relevant tokens is infinitely cheaper and yields better model accuracy than blindly dumping 8,000 tokens.</p><h3>Tactic 4: Circuit Breakers</h3><p>External APIs fail. Rate limits get exhausted. If your application crashes when LLM API throws a 502 Bad Gateway, your architecture is brittle.</p><p>Your gateway must implement strict circuit breakers. </p><p>If the primary provider times out or degrades, the gateway must instantly and transparently reroute the exact payload to a backup provider (e.g., failing over from OpenAI to Anthropic). </p><p>Graceful degradation is a mandatory requirement, not a feature.</p><div><hr></div><h2>Conclusion</h2><p>Large Language Models are not magic brains. They are commodity compute.</p><p>The value of your engineering team is not in writing a clever system prompt. The value is in building the caching, routing, pruning, and abstraction infrastructure that makes running that prompt economically viable.</p><p>If you build a thin wrapper, the API provider will eventually consume your margins. </p><p>Build the moat, or prepare to join the graveyard.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.binarybox.org/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">Thanks for reading BinaryBox! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><p></p><p></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Do you really need a Vector Database for your AI Product?]]></title><description><![CDATA[Before you sign a massive SaaS contract for a dedicated vector engine, you need to understand the physics of the hardware you are renting.]]></description><link>https://www.binarybox.org/p/do-you-really-need-a-vector-database</link><guid isPermaLink="false">https://www.binarybox.org/p/do-you-really-need-a-vector-database</guid><dc:creator><![CDATA[Ashok Vishwakarma]]></dc:creator><pubDate>Tue, 24 Mar 2026 06:00:50 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!_Lc8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fa95570-4e88-4df3-97f2-f82586cd81c7_1200x675.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_!_Lc8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fa95570-4e88-4df3-97f2-f82586cd81c7_1200x675.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_Lc8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fa95570-4e88-4df3-97f2-f82586cd81c7_1200x675.jpeg 424w, https://substackcdn.com/image/fetch/$s_!_Lc8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fa95570-4e88-4df3-97f2-f82586cd81c7_1200x675.jpeg 848w, https://substackcdn.com/image/fetch/$s_!_Lc8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fa95570-4e88-4df3-97f2-f82586cd81c7_1200x675.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!_Lc8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fa95570-4e88-4df3-97f2-f82586cd81c7_1200x675.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_Lc8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fa95570-4e88-4df3-97f2-f82586cd81c7_1200x675.jpeg" width="1200" height="675" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0fa95570-4e88-4df3-97f2-f82586cd81c7_1200x675.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:675,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Comparing 10 Vector Database APIs For AI | Nordic APIs |&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Comparing 10 Vector Database APIs For AI | Nordic APIs |" title="Comparing 10 Vector Database APIs For AI | Nordic APIs |" srcset="https://substackcdn.com/image/fetch/$s_!_Lc8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fa95570-4e88-4df3-97f2-f82586cd81c7_1200x675.jpeg 424w, https://substackcdn.com/image/fetch/$s_!_Lc8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fa95570-4e88-4df3-97f2-f82586cd81c7_1200x675.jpeg 848w, https://substackcdn.com/image/fetch/$s_!_Lc8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fa95570-4e88-4df3-97f2-f82586cd81c7_1200x675.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!_Lc8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0fa95570-4e88-4df3-97f2-f82586cd81c7_1200x675.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>Last week, I sat in an architecture review with a client who had just secured Series A funding. They were building a standard Retrieval-Augmented Generation (RAG) pipeline for their internal documents. </p><p>Before anyone had written a single line of backend logic, the engineering lead proudly displayed a slide proposing a six-figure enterprise contract with a dedicated Vector Database.</p><p>When I asked why we weren&#8217;t just using Postgres, the answer was immediate</p><p><em><strong> &#8220;Because this is an AI app. You need a Vector DB for AI.&#8221;</strong></em></p><p>This is the exact kind of hype-driven development that destroys startup runways.</p><p>At the physical level, Vector Databases are not magic AI boxes. They do not understand &#8220;meaning,&#8221; &#8220;context,&#8221; or &#8220;semantics.&#8221; </p><p>They are simply C++ or Rust memory allocators navigating multi-dimensional mathematical graphs. </p><p>To do this quickly, they trade exact accuracy for speed, and they force you to pay an absolute fortune in RAM to do it.</p><p>Before you sign a massive SaaS contract for a dedicated vector engine, you need to understand the physics of the hardware you are renting.</p><h2>The Brute Force Math</h2><p>To understand why traditional databases fail at vector search, you have to look at the math of a &#8220;Vector.&#8221;</p><p>An OpenAI <code>text-embedding-3-small</code> embedding is a 1,536-dimensional array of floating-point numbers. In physical memory, a single 32-bit float consumes 4 bytes.</p><p><code>1,536 dimensions &#215; 4 bytes = 6,144 bytes (6 KB) per vector</code></p><p>If you want to find the closest vectors to a user&#8217;s query using exact math, a process called Exact K-Nearest Neighbors (KNN) which your CPU must calculate the cosine similarity between the query vector and every single row in the database.</p><p>Let&#8217;s do the memory bandwidth math on a small 1-million-row table</p><p><code>1,000,000 rows &#215; 6 KB = 6.1 Gigabytes of data</code></p><p>To answer one user query, </p><ul><li><p>the CPU must pull <strong>6.1 GB</strong> of data from RAM through the memory bus, </p></li><li><p>load it into the <strong>L1 cache</strong>, </p></li><li><p>and execute millions of <strong>AVX-512 SIMD</strong> (Single Instruction, Multiple Data) dot-product operations.</p></li></ul><p>Even on modern DDR5 RAM peaking at 50 GB/s of bandwidth, a single concurrent user doing an Exact KNN search will consume 12% of your entire server&#8217;s memory bandwidth. </p><p>If you get 10 concurrent searches, your CPU is completely starved for data. The system grinds to an absolute halt.</p><p>Even the traditional B-Trees cannot save you. </p><p>A B-Tree relies on 1-dimensional inequalities (<em>Is X &gt; 10? Go right</em>). You cannot sort or bisect 1,536 dimensions simultaneously.</p><h2>HNSW (Hierarchical Navigable Small World)</h2><p>If Exact KNN locks up the CPU, how do Vector DBs return results in 20 milliseconds?</p><p>They don&#8217;t do exact searches. They cheat.</p><p>Vector databases rely on <strong>Approximate Nearest Neighbor (ANN)</strong> algorithms.</p><p>They accept that finding the <em>perfect</em> match is computationally impossible at scale, so they settle for finding a <em>very good</em> match almost instantly.</p><p>The undisputed king of these algorithms is <strong><a href="https://en.wikipedia.org/wiki/Hierarchical_navigable_small_world">HNSW</a></strong>.</p><p>Do not let the academic name intimidate you. HNSW is just a multi-layered skip-list mapped over a proximity graph. </p><p>Imagine you are driving from New York to a specific house in a suburb of Los Angeles</p><h4>The Top Layer (Interstates)</h4><p>You don&#8217;t take local roads across the country. You get on an interstate. </p><p>In HNSW, the top layer has very few nodes, but they have long-distance links. </p><p>The search algorithm drops in here and makes massive, cross-graph jumps toward the general cluster of the target.</p><h4>The Middle Layers (City Roads)</h4><p>Once you are near Los Angeles, you drop down a layer. </p><p>There are more nodes here, connected by shorter links. </p><p>You navigate to the correct neighborhood.</p><h4>The Bottom Layer (Local Streets)</h4><p>You drop to the base layer, which contains every single vector in the database, and you traverse the local streets until you hit the closest possible house (a local minimum).</p><p>HNSW is a masterpiece of algorithmic engineering. It reduces a catastrophic <code>O(N)</code> full table scan into a blisteringly fast <code>O(log N)</code> graph traversal.</p><p>But it comes with a brutal physical cost called <strong>Pointer Chasing.</strong></p><h2>Why NVMe SSDs Hate HNSW (Pointer Chasing)</h2><p>Traditional relational databases are famous for being disk-friendly because they exploit <strong>Locality of Reference</strong>. </p><p>B-Tree nodes are packed cleanly into contiguous 8KB blocks (pages) on your SSD. When Postgres needs an index node, it pulls a single 8KB block into memory, and all the sequential keys are right there next to each other.</p><p>HNSW graphs are the exact opposite.</p><p>An HNSW index is a giant, chaotic web of pointers (memory addresses) pointing to other pointers across multiple layers. </p><p>The nodes are scattered randomly across the heap during insertion.</p><p>Traversing this graph means jumping wildly from memory address to memory address. </p><p>If your HNSW index does not fit in RAM and is forced onto a Solid-State Drive, following those pointers requires thousands of <strong>Random Disk Reads</strong> per query.</p><p>A standard NVMe SSD takes roughly 100 microseconds (<code>&#181;s</code>) to complete a random 4KB read. If an HNSW search requires 200 graph hops to find the nearest neighbor</p><p><code>200 hops &#215; 100 &#181;s = 20 milliseconds of pure disk latency</code></p><p>That sounds fast, until you realize this is for <em>one</em> query. </p><p>If your app is doing 1,000 queries per second, your SSD must sustain 200,000 random IOPS. </p><p>Even the most expensive AWS <code>io2 Block Express</code> volumes will buckle under that kind of random I/O queue depth. </p><p>Your 20ms latency will instantly spike to 2 seconds as the disk controllers choke.</p><p>Furthermore, pointer chasing completely defeats the OS Page Cache and the CPU&#8217;s hardware prefetchers. </p><p>The CPU cannot guess which memory address the graph will jump to next, resulting in continuous L3 cache misses.</p><h2>The RAM Tax</h2><p>Here is the physical reality of vector search</p><p><strong>To get the sub-50ms latency that Vector DBs advertise, the entire HNSW index must physically live in RAM.</strong></p><p>This brings us to the invoice (cost of the RAM). </p><p>RAM is exponentially more expensive than NVMe storage. Let&#8217;s do the math on a production-scale deployment of 100 million vectors.</p><ul><li><p><strong>Vector Payload</strong> - <code>100,000,000 &#215; 6 KB (1536-dim floats) = 600 GB</code></p></li><li><p><strong>HNSW Graph Overhead</strong> - Each node in HNSW maintains bidirectional pointers to its neighbors across multiple layers. This pointer overhead usually adds 30% to 50% to the base vector size. Let&#8217;s add 200 GB.</p></li></ul><p>To serve 100 million vectors, you need <strong>800 GB of RAM</strong>.</p><p>Storing 800 GB on a standard Postgres SSD costs about $65 a month. Holding 800 GB in an AWS <code>r6a.24xlarge</code> memory-optimized instance costs <strong>$5,300 a month</strong>.</p><p>When you buy a dedicated Vector Database, you are not buying better &#8220;AI.&#8221;</p><p>You are buying an expensive fleet of high-RAM cloud instances to hold a massive, chaotic pointer graph in volatile memory because the algorithm physically cannot survive on a disk.</p><h2>What you should do?</h2><p>Do not subsidize a SaaS company&#8217;s valuation because you think standard infrastructure can&#8217;t handle vector math. </p><p>Here is the architectural framework you should use before signing a vendor contract</p><h3>Use Postgres (<code>pgvector</code>)</h3><p><strong>If you have fewer than 5 million vectors</strong>, you do not have a scale problem. You have a standard CRUD problem.</p><p>Install the <code>pgvector</code> extension on your existing Postgres instance. </p><p>Postgres is perfectly capable of building an HNSW index and holding it in its <code>shared_buffers</code> (RAM). </p><p>You save thousands of dollars, you eliminate a fragile network hop in your infrastructure, and you keep your relational data and your embeddings in the exact same ACID-compliant transaction block. </p><p>You can <code>JOIN</code> your semantic search results directly against your user permission tables in a single query.</p><h3>Use a Dedicated Vector DB (Pinecone, Milvus, Qdrant)</h3><p>You only graduate to a dedicated vector engine when your index physically outgrows the RAM limits of a single, massive database instance.</p><p>When you hit 50 million, 100 million, or a billion vectors, a single Postgres node will OOM (Out of Memory) trying to fit the HNSW graph into <code>shared_buffers</code>. </p><p><em>That</em> is the exact moment you pay a premium for a distributed vector database. </p><p>You are paying them to shard the massive HNSW graph across multiple clustered nodes and handle the distributed scatter-gather networking required to query it.</p><div><hr></div><h2>Conclusion</h2><p>Architecture requires alignment between the physical realities of the hardware and the economic realities of the business.</p><p>HNSW is a brilliant algorithm, but it is an unapologetic memory glutton. </p><p>It defeats disk I/O, thrashes CPU caches, and demands expensive DDR5 RAM to function at scale. </p><p>Start with Postgres, monitor your memory saturation, and scale out to a distributed vector engine only when the physics of the graph demand it.</p><p>Don&#8217;t buy a distributed system until you have a distributed problem.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.binarybox.org/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">Thanks for reading BinaryBox! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><p></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Thought - Why Postgres is a dangerous default]]></title><description><![CDATA[Nobody gets fired for choosing Postgres. It is the safest, most defensible technical decision you can make. Until it isn't. Especially when you are building a highly concurrent, event-driven logger.]]></description><link>https://www.binarybox.org/p/thought-why-postgres-is-a-dangerous</link><guid isPermaLink="false">https://www.binarybox.org/p/thought-why-postgres-is-a-dangerous</guid><dc:creator><![CDATA[Ashok Vishwakarma]]></dc:creator><pubDate>Thu, 19 Mar 2026 06:00:52 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!dbpC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a933fd4-4ab4-4f2c-8ff8-45c12b4c87b3_1024x521.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_!dbpC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a933fd4-4ab4-4f2c-8ff8-45c12b4c87b3_1024x521.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dbpC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a933fd4-4ab4-4f2c-8ff8-45c12b4c87b3_1024x521.png 424w, https://substackcdn.com/image/fetch/$s_!dbpC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a933fd4-4ab4-4f2c-8ff8-45c12b4c87b3_1024x521.png 848w, https://substackcdn.com/image/fetch/$s_!dbpC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a933fd4-4ab4-4f2c-8ff8-45c12b4c87b3_1024x521.png 1272w, https://substackcdn.com/image/fetch/$s_!dbpC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a933fd4-4ab4-4f2c-8ff8-45c12b4c87b3_1024x521.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dbpC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a933fd4-4ab4-4f2c-8ff8-45c12b4c87b3_1024x521.png" width="1024" height="521" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3a933fd4-4ab4-4f2c-8ff8-45c12b4c87b3_1024x521.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:521,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Upgrading PostgreSQL with no data loss and minimal downtime | Tech blog |  Palark&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Upgrading PostgreSQL with no data loss and minimal downtime | Tech blog |  Palark" title="Upgrading PostgreSQL with no data loss and minimal downtime | Tech blog |  Palark" srcset="https://substackcdn.com/image/fetch/$s_!dbpC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a933fd4-4ab4-4f2c-8ff8-45c12b4c87b3_1024x521.png 424w, https://substackcdn.com/image/fetch/$s_!dbpC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a933fd4-4ab4-4f2c-8ff8-45c12b4c87b3_1024x521.png 848w, https://substackcdn.com/image/fetch/$s_!dbpC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a933fd4-4ab4-4f2c-8ff8-45c12b4c87b3_1024x521.png 1272w, https://substackcdn.com/image/fetch/$s_!dbpC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a933fd4-4ab4-4f2c-8ff8-45c12b4c87b3_1024x521.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>Nobody gets fired for choosing Postgres. </p><p>It is the safest, most defensible technical decision you can make. Until it isn&#8217;t. Especially when you are building a highly concurrent, event-driven logger.</p><p>You pick it because it handles everything perfectly on day one, completely ignoring that you are buying a general-purpose engine for what might be a highly specialized problem.</p><p>We do this constantly in software. We slap a UUIDv4 on a primary key because it is convenient, blindly accepting the B-Tree fragmentation it guarantees at scale. </p><p>We spin up Postgres because it is the industry standard, ignoring what its storage engine actually does to our specific data shape.</p><p>Convenience dictates the architecture. Physics dictates the bill.</p><h2>The cost of MVCC Write</h2><p>Look at how Postgres manages concurrency. Multi-Version Concurrency Control (MVCC) is a brilliant mechanism. It allows readers and writers to operate simultaneously by creating new tuple versions instead of modifying data in place.</p><p>Let&#8217;s be absolutely clear.</p><p>If you are building a standard B2B SaaS application, with users, organizations, billing tables, and dynamic records, Postgres is flawless. If you are building a banking ledger where balances update constantly, MVCC is your best friend.</p><p>But if you are building an event log, a sensor stream, or an audit trail, MVCC is a parasite.</p><p>Consider a standard telemetry or event logging table. The schema looks entirely innocent</p><pre><code><code>CREATE TABLE user_events (
    event_id UUID PRIMARY KEY,
    user_id BIGINT,
    event_type VARCHAR(50),
    payload JSONB,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Executed 50,000 times a second
INSERT INTO user_events (event_id, user_id, event_type, payload)
VALUES ('...', 123, 'click', '{"button": "signup"}');</code></code></pre><p>To the developer, this is a simple, lightweight append operation. To the Postgres storage engine, this is a massive overhead event.</p><p>Your rows are immutable the second they hit the disk. Yet, every single insert carries a hidden 23-byte tuple header (<code>xmin</code>, <code>xmax</code>, <code>cmin</code>, <code>cmax</code>) tracking version visibility for concurrency that will never happen.</p><p>At 50,000 inserts a second, you are paying a massive, constant write tax on data that will never change. You are generating gigabytes of Write-Ahead Log (WAL) just to track ghosts.</p><h2>8KB at a Time</h2><p>When you do actually update or delete records in a highly active table, the architecture fights you in a completely different way.</p><pre><code><code>-- You think you are modifying data in place. You aren't.
UPDATE user_sessions 
SET last_seen = NOW() 
WHERE session_id = 'abc-123';</code></code></pre><p>Postgres does not delete old rows. It leaves the dead tuple sitting exactly where it was on the physical 8KB page. It writes the new, updated row to a new location. A background worker called autovacuum is supposed to sweep through eventually and mark that old space as reusable.</p><p>Under a heavy write load, autovacuum loses the race. Dead tuples accumulate faster than the database can process them.</p><p>Because live and dead records share the exact same physical pages, the query planner cannot skip the graveyard. If your table has 10 million live rows and 40 million dead ones, your hardware is pulling massive amounts of garbage from the disk into your buffer pool just to find the active data. The engine literally chokes on its own history.</p><p>As <strong><a href="https://www.cs.cmu.edu/~pavlo/">Andy Pavlo</a></strong> at CMU has pointed out, if someone were building a new MVCC database today, they would not implement it the way Postgres does. Its append-only storage design is a relic of the 1980s that predates log-structured storage patterns entirely.</p><h2>The Snapshot Collision</h2><p>One day someone asks for a dashboard. You run a long analytical query against this live operational data.</p><pre><code><code>-- The Data Analyst runs this at 9:00 AM
SELECT date_trunc('hour', created_at), count(*)
FROM user_events
GROUP BY 1
ORDER BY 1;</code></code></pre><p>Running a daily sales report on a 5-gigabyte SaaS database is fine. Running a 2-hour aggregation on a table absorbing 50,000 sensor readings a second is a death sentence.</p><p>To guarantee consistent reads, Postgres holds the transaction snapshot open. While that two-hour report runs, autovacuum is paralyzed.</p><p>It cannot clean up any dead tuples that fall behind that active transaction horizon. Your dashboard is actively blocking garbage collection for the entire operational database. </p><p>Every <code>UPDATE</code> happening on your site during those two hours leaves a permanent scar on the disk until the report finishes.</p><p>Friction generates heat. Heat generates wear. Wear destroys your query latency. Postgres was simply not designed to serve heavy OLTP and OLAP from the same instance under load.</p><h2>The Optimization Treadmill</h2><p>This is when you step onto the Optimization Treadmill. You do not fix the architecture. You treat the symptoms.</p><h4>Step 1 - The Index Trap</h4><p>Write throughput dips, so you add a composite index to speed up the read queries causing the locks. You just amplified your write penalty. Every insert now has to update multiple B-Trees.</p><h4>Step 2 - The Vacuum Illusion</h4><p>The table bloats, so you aggressively tune the background workers.</p><pre><code><code>ALTER TABLE user_sessions 
SET (autovacuum_vacuum_scale_factor = 0.01);</code></code></pre><p>You force the database to vacuum constantly. You are now burning precious CPU cycles fighting your own insert rate.</p><h4>Step 3 - Hardware Scaling</h4><p>CPU spikes, so you upgrade the instance class. You double the RAM. You provision higher IOPS.</p><p>Every single one of these interventions is the technically correct response to a real symptom. You are doing exactly what an experienced DBA would do. But none of it changes your trajectory. You are fighting an architectural ceiling, not a misconfiguration.</p><p>The treadmill only speeds up. Each fix buys you a few months of runway before the database collects its tax again.</p><h2>How to Spot the Treadmill Early</h2><p>The most critical decision you can make is recognizing the treadmill before you get on it. Stop treating Postgres as a zero-cost default. Look at the physical reality of your data before you write the schema.</p><ul><li><p>Are your writes predominantly inserts with no updates?</p></li><li><p>Are the rows permanently immutable once written?</p></li><li><p>Is your data volume growing by 50 percent year over year?</p></li><li><p>Do you need to run heavy analytics against the same live table?</p></li></ul><p>If you nod your head to any of those, the architectural mismatch is already baked in. The only variable is how much engineering time and AWS budget you burn before you stop asking how to tune the database, and start asking the question you should have asked on day one.</p><p>Are we actually building a general-purpose OLTP system?</p><h2>The HTAP Escape</h2><p>If you recognize the treadmill early, you can escape it. If you actually need to serve heavy OLTP and OLAP concurrently from the same system without melting your disks, you need an architecture designed for Hybrid Transactional/Analytical Processing (HTAP).</p><p>When Postgres is no longer the default, you have three primary paths</p><h3>1. <a href="https://www.singlestore.com/">SingleStore</a></h3><p>SingleStore (formerly MemSQL) solves the OLTP/OLAP collision by physically splitting the storage engine under the hood. It uses an in-memory rowstore for blazing-fast transactional inserts and a disk-based columnstore for your analytical queries.</p><p>It is true HTAP. You get millisecond ingest and sub-second aggregations on the exact same cluster. It speaks the MySQL wire protocol, making integration trivial.</p><p>But, it is proprietary and expensive. The in-memory rowstore demands that your operational working set fits entirely in RAM. You are trading software friction for a massive hardware bill.</p><h3>2. <a href="https://www.pingcap.com/">TiDB</a></h3><p>TiDB separates compute from storage entirely. It uses a Raft-based distributed key-value store (TiKV) for your transactional inserts, and asynchronously replicates that data to a columnar engine (TiFlash) for analytics. The smart query planner automatically routes your dashboard queries to the column nodes and your point-writes to the row nodes.</p><p>It scales horizontally forever. You can run massive analytical reports against TiFlash without ever locking an operational row in TiKV.</p><p>But, it has severe operational complexity. You do not just &#8220;spin up&#8221; TiDB. Running the control plane, compute nodes, row storage nodes, and column storage nodes requires a dedicated infrastructure team. It is a Ferrari; you have to hire the mechanics.</p><h3>3. <a href="https://kafka.apache.org/">Kafka</a> + <a href="https://clickhouse.com/">ClickHouse</a> (Split Stack)</h3><p>If you cannot justify HTAP licensing or operational overhead, stop trying to force both workloads into one database. Write your immutable events to an append-only log (Kafka). Consume that log into a pure columnar database (ClickHouse) for your dashboards.</p><p>The physics align perfectly. Kafka&#8217;s sequential writes effortlessly absorb the OLTP load. ClickHouse&#8217;s columnar compression destroys the OLAP load. Both systems run at absolute maximum efficiency.</p><p>But, you now maintain two distinct distributed systems and the pipeline connecting them. Eventual consistency is guaranteed; immediate consistency is impossible.</p><div><hr></div><h1>Conclusion</h1><p>There is a recurring theme in engineering failures, we mistake popularity for universal fit.</p><p>Postgres is arguably the greatest relational database ever built. But it is a machine with specific operating parameters. </p><p>When you force an append-only, high-velocity stream into an MVCC engine, you are not testing the limits of Postgres. You are testing the limits of your infrastructure budget.</p><p>Stop letting convenience dictate your architecture. The cost of learning a specialized database like ClickHouse or Kafka today is infinitely lower than the cost of fighting the Optimization Treadmill tomorrow.</p><p>Physics always wins. Choose your database accordingly.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.binarybox.org/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">Thanks for reading BinaryBox! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p>]]></content:encoded></item><item><title><![CDATA[Research - A Formal Threshold Model for B-Tree Performance Degradation Under Random Primary Keys in OLTP Systems]]></title><description><![CDATA[We prove that this degradation is a physical limitation of B-Tree mechanics under random insertion, compounded by Write Amplification Factor (WAF) penalties, rather than a hardware or traffic-scaling]]></description><link>https://www.binarybox.org/p/research-a-formal-threshold-model</link><guid isPermaLink="false">https://www.binarybox.org/p/research-a-formal-threshold-model</guid><dc:creator><![CDATA[Ashok Vishwakarma]]></dc:creator><pubDate>Tue, 17 Mar 2026 06:01:02 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!F1Pb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9af60071-dc0d-4682-af0c-647161e40d7c_1720x900.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_!F1Pb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9af60071-dc0d-4682-af0c-647161e40d7c_1720x900.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!F1Pb!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9af60071-dc0d-4682-af0c-647161e40d7c_1720x900.png 424w, https://substackcdn.com/image/fetch/$s_!F1Pb!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9af60071-dc0d-4682-af0c-647161e40d7c_1720x900.png 848w, https://substackcdn.com/image/fetch/$s_!F1Pb!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9af60071-dc0d-4682-af0c-647161e40d7c_1720x900.png 1272w, https://substackcdn.com/image/fetch/$s_!F1Pb!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9af60071-dc0d-4682-af0c-647161e40d7c_1720x900.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!F1Pb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9af60071-dc0d-4682-af0c-647161e40d7c_1720x900.png" width="1456" height="762" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9af60071-dc0d-4682-af0c-647161e40d7c_1720x900.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:762,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:109405,&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://www.binarybox.org/i/191116240?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9af60071-dc0d-4682-af0c-647161e40d7c_1720x900.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_!F1Pb!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9af60071-dc0d-4682-af0c-647161e40d7c_1720x900.png 424w, https://substackcdn.com/image/fetch/$s_!F1Pb!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9af60071-dc0d-4682-af0c-647161e40d7c_1720x900.png 848w, https://substackcdn.com/image/fetch/$s_!F1Pb!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9af60071-dc0d-4682-af0c-647161e40d7c_1720x900.png 1272w, https://substackcdn.com/image/fetch/$s_!F1Pb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9af60071-dc0d-4682-af0c-647161e40d7c_1720x900.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><figcaption class="image-caption">Image credits Toptal</figcaption></figure></div><p>The adoption of UUIDv4 as a primary key in OLTP databases has become a widespread default, driven by ORM convenience and distributed system requirements. </p><p><strong><a href="https://zenodo.org/records/19034540">This paper</a></strong> demonstrates that UUIDv4 primary keys guarantee severe, predictable performance degradation as table size grows. We introduce the Buffer Saturation Ratio (BSR) and derive a closed-form threshold (N<sup>*</sup>) that predicts exactly when write latency will spike. </p><p>We prove that this degradation is a physical limitation of B-Tree mechanics under random insertion, compounded by Write Amplification Factor (WAF) penalties, rather than a hardware or traffic-scaling failure.</p><h2>The Anatomy of a Deferred Crisis</h2><p>Modern frameworks make it trivial to assign a random, 128-bit string as a primary key. Distributed ID generation solves immediate engineering headaches. It prevents sequence contention. It hides entity counts from users.</p><p>But it introduces a delayed tax on your storage layer.</p><p>Engineers rarely observe the cost of UUIDv4 during the first year of a project. Databases aggressively cache active indexes in RAM. As long as the primary key index fits entirely within the database buffer pool, random inserts perform acceptably.</p><p>The crisis arrives silently. The index quietly outgrows the allocated memory. The database begins reading cold pages from the physical disk to complete routine inserts. Write latency jumps by two orders of magnitude. The typical engineering response, upgrading the instance class which fails to resolve the underlying physics.</p><h2>B-Tree Mechanics and the Fill Factor Penalty</h2><p>Relational databases use B-Tree variants to store indexes. Sequential keys, such as BigInt sequences or UUIDv7, append new records to the rightmost edge of the tree. The database keeps that single, active leaf node hot in memory.</p><p>UUIDv4 values possess zero temporal locality. Every insert targets a random location in the B-Tree.</p><p>When you insert a record into a random leaf node that is already full, the database executes a page split. It allocates a new page (16KB in MySQL InnoDB, 8KB in PostgreSQL), transfers half the records, and updates the parent nodes.</p><p>Sequential inserts achieve a high index fill factor (f &#8776; 0.90 to 0.94). Random UUIDv4 inserts guarantee continuous page splits, driving the equilibrium fill factor down to approximately 0.50. You are permanently storing half-empty pages. Your index requires twice the RAM just to exist.</p><h2>The Buffer Saturation Ratio (BSR)</h2><p>To predict performance failure, we must track the relationship between index size and available memory. We define the Buffer Saturation Ratio (BSR)</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;BSR = \\frac{B_{pool}}{I_{size}}&quot;,&quot;id&quot;:&quot;MFHVRXGSZK&quot;}" data-component-name="LatexBlockToDOM"></div><p>Where B<sub>pool</sub> is the configured memory for caching (InnoDB Buffer Pool or PostgreSQL <code>shared_buffers</code>), and I<sub>size</sub> is the total size of the primary key index.</p><p>When BSR &#8805; 1.0, the entire index resides in memory. Writes are fast.<br>When BSR &lt; 1.0 , the index exceeds available RAM.</p><p>At BSR &lt; 1.0, every random insert carries a cache miss probability (P<sub>miss</sub>)</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;P_{miss} = 1 - BSR&quot;,&quot;id&quot;:&quot;TZQPTRAXYL&quot;}" data-component-name="LatexBlockToDOM"></div><p>When a cache miss occurs, the database evicts a page to load the target leaf node from disk. Because UUIDv4 targets pages uniformly, the newly loaded page is highly unlikely to be reused before it is evicted again. This creates LRU eviction thrashing.</p><p>Your expected insert latency (L<sub>insert</sub>) becomes completely dominated by disk I/O</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;L_{insert} = L_{cpu} + (P_{miss} \\times L_{io})&quot;,&quot;id&quot;:&quot;CESZUJJVNM&quot;}" data-component-name="LatexBlockToDOM"></div><h2>Deriving the Threshold Row Count (N<sup>*</sup>)</h2><p>We can calculate the exact row count where a database will fall off the performance cliff. First, we model the projected index size</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;I_{size} = \\frac{N \\times (K_{size} + P_{overhead})}{f}&quot;,&quot;id&quot;:&quot;XTXVBRBNEH&quot;}" data-component-name="LatexBlockToDOM"></div><p>Where</p><ul><li><p>N = Number of rows</p></li><li><p>K<sub>size</sub>= Key size in bytes (16 for binary UUID, 36 for char UUID, 8 for BigInt)</p></li><li><p>P<sub>overhead</sub> = Pointer overhead (roughly 8 bytes)</p></li><li><p>f = Fill factor (0.50 for UUIDv4, 0.94 for BigInt)</p></li></ul><p>To find the threshold row count (N<sup>*</sup>), we set I<sub>size</sub> equal to B<sub>pool </sub>(BSR = 1.0) and solve for N</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;N^* = \\frac{B_{pool} \\times f}{K_{size} + P_{overhead}}&quot;,&quot;id&quot;:&quot;ZDMSHGLYPT&quot;}" data-component-name="LatexBlockToDOM"></div><p>This equation allows architects to project the exact lifespan of a database schema configuration.</p><h2>Write Amplification Factor (WAF)</h2><p>Random inserts punish the storage layer beyond just cache misses. They generate massive Write Amplification Factor (WAF) in the Write-Ahead Log (WAL).</p><p>The write amplification for a UUIDv4 index follows a logarithmic curve</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;WAF_{uuid} = 1 + \\left(\\frac{2}{m}\\right) \\times \\log_2\\left(\\frac{N}{M}\\right)&quot;,&quot;id&quot;:&quot;NBQIQZZIXA&quot;}" data-component-name="LatexBlockToDOM"></div><p>Where m is the B-Tree order (roughly 80 for InnoDB at 16KB pages with 200-byte rows), N is total rows, and M is the number of rows that fit in the buffer pool.</p><p>Your total write amplification multiplies by your secondary indexes (k)</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;WAF_{total} = (k + 1) \\times WAF_{uuid}&quot;,&quot;id&quot;:&quot;OXLKBUZQIS&quot;}" data-component-name="LatexBlockToDOM"></div><p>MySQL InnoDB uses clustered indexes. The massive, random primary key is duplicated into the leaf nodes of every secondary index. PostgreSQL uses heap tables, bypassing clustered index bloat, but secondary indexes still suffer the brutal page split penalty and identical WAF multipliers.</p><h2>Case study</h2><p>One of my client ran a package scan event log using a <code>char(36)</code> UUIDv4 primary key on a 16 GB RDS instance equipped with a 12 GB buffer pool.</p><p>During the first year, at 50 million rows, performance remained nominal. Their BSR sat at 8.0. The buffer pool easily absorbed the random writes.</p><p>The table eventually reached 500 million rows. The <code>char(36)</code> key, combined with the 0.50 fill factor, swelled the index size to roughly 15 GB.</p><p>Their BSR dropped to 0.80. Write latency instantly climbed from 2 ms to 200 ms. CPU utilization on the RDS instance pinned at 90 percent, entirely consumed by managing LRU evictions.</p><p>They upgraded the RDS instance class twice. Neither upgrade resolved the latency. Each vertical scaling event raised CPU, RAM, and the buffer pool proportionally, but the BSR remained strictly below 1.0. The index remained larger than the pool.</p><p>Hardware scaling cannot outrun mathematical thresholds. The only viable solution was migrating the primary key to a sequential format.</p><h2>The N<sup>*</sup> Decision Matrix</h2><p>Applying the N<sup>*</sup> formula to standard infrastructure configurations reveals the severe capacity penalty of UUIDv4 strings</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!jV8A!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b3c774a-e626-4712-9967-8976142a32a6_1920x745.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jV8A!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b3c774a-e626-4712-9967-8976142a32a6_1920x745.png 424w, https://substackcdn.com/image/fetch/$s_!jV8A!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b3c774a-e626-4712-9967-8976142a32a6_1920x745.png 848w, https://substackcdn.com/image/fetch/$s_!jV8A!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b3c774a-e626-4712-9967-8976142a32a6_1920x745.png 1272w, https://substackcdn.com/image/fetch/$s_!jV8A!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b3c774a-e626-4712-9967-8976142a32a6_1920x745.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jV8A!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b3c774a-e626-4712-9967-8976142a32a6_1920x745.png" width="1456" height="565" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3b3c774a-e626-4712-9967-8976142a32a6_1920x745.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:565,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:125351,&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://www.binarybox.org/i/191116240?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b3c774a-e626-4712-9967-8976142a32a6_1920x745.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_!jV8A!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b3c774a-e626-4712-9967-8976142a32a6_1920x745.png 424w, https://substackcdn.com/image/fetch/$s_!jV8A!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b3c774a-e626-4712-9967-8976142a32a6_1920x745.png 848w, https://substackcdn.com/image/fetch/$s_!jV8A!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b3c774a-e626-4712-9967-8976142a32a6_1920x745.png 1272w, https://substackcdn.com/image/fetch/$s_!jV8A!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b3c774a-e626-4712-9967-8976142a32a6_1920x745.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 32 GB server running a <code>char(36)</code> UUIDv4 index chokes at 273 million rows. The exact same hardware running a BigInt handles 2.25 billion rows. You are paying a 400 percent RAM tax for a framework default.</p><div><hr></div><h2>Conclusion</h2><p>UUIDv4 primary keys constitute a systemic architectural flaw in high-throughput OLTP databases. They actively defeat database caching mechanisms and maximize physical disk I/O.</p><p>Engineers must stop treating database performance degradation as a generic symptom of traffic scaling. Use the N<sup>*</sup> threshold formula to project your schema&#8217;s structural limits before executing a <code>CREATE TABLE</code> statement.</p><p>If distributed ID generation is a hard requirement, adopt temporally sequential identifiers like UUIDv7 or ULID. Align your data structures with the physical constraints of B-Tree mechanics.</p><p>Read the paper here</p><p><strong><a href="https://zenodo.org/records/19034540">https://zenodo.org/records/19034540 </a></strong></p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.binarybox.org/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">Thanks for reading BinaryBox! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p>]]></content:encoded></item><item><title><![CDATA[Thought - Why Banks Can't "Just Rewrite" COBOL in Java/Python/Go?]]></title><description><![CDATA[This is technical debt. We are going to rewrite the Core Ledger in Java microservices. We will be cloud-native]]></description><link>https://www.binarybox.org/p/thought-why-banks-cant-just-rewrite</link><guid isPermaLink="false">https://www.binarybox.org/p/thought-why-banks-cant-just-rewrite</guid><dc:creator><![CDATA[Ashok Vishwakarma]]></dc:creator><pubDate>Thu, 12 Mar 2026 06:01:49 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!e2QY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2dd55e57-b708-4a2a-8ee3-300accc387de_1198x627.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_!e2QY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2dd55e57-b708-4a2a-8ee3-300accc387de_1198x627.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!e2QY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2dd55e57-b708-4a2a-8ee3-300accc387de_1198x627.jpeg 424w, https://substackcdn.com/image/fetch/$s_!e2QY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2dd55e57-b708-4a2a-8ee3-300accc387de_1198x627.jpeg 848w, https://substackcdn.com/image/fetch/$s_!e2QY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2dd55e57-b708-4a2a-8ee3-300accc387de_1198x627.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!e2QY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2dd55e57-b708-4a2a-8ee3-300accc387de_1198x627.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!e2QY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2dd55e57-b708-4a2a-8ee3-300accc387de_1198x627.jpeg" width="1198" height="627" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2dd55e57-b708-4a2a-8ee3-300accc387de_1198x627.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:627,&quot;width&quot;:1198,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Anthropic's COBOL-Crunching AI Shakes IBM, But Opens Big New Deals for  Indian IT Giants, ETEnterpriseai&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Anthropic's COBOL-Crunching AI Shakes IBM, But Opens Big New Deals for  Indian IT Giants, ETEnterpriseai" title="Anthropic's COBOL-Crunching AI Shakes IBM, But Opens Big New Deals for  Indian IT Giants, ETEnterpriseai" srcset="https://substackcdn.com/image/fetch/$s_!e2QY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2dd55e57-b708-4a2a-8ee3-300accc387de_1198x627.jpeg 424w, https://substackcdn.com/image/fetch/$s_!e2QY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2dd55e57-b708-4a2a-8ee3-300accc387de_1198x627.jpeg 848w, https://substackcdn.com/image/fetch/$s_!e2QY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2dd55e57-b708-4a2a-8ee3-300accc387de_1198x627.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!e2QY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2dd55e57-b708-4a2a-8ee3-300accc387de_1198x627.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>It happens every five years. A new CTO arrives at a Global 500 bank. </p><p>They look at the &#8220;Green Screen&#8221; terminals, the 40-year-old IBM Z/OS mainframes, and the millions of lines of COBOL. </p><p>They cringe.</p><p>&#8220;This is legacy,&#8221; they declare. </p><p>&#8220;This is technical debt. We are going to rewrite the Core Ledger in Java microservices. We will be cloud-native.&#8221;</p><p>Three years and $50 million later, the project is quietly cancelled. </p><p>The CTO moves on to a different company. </p><p><strong>The COBOL remains.</strong></p><p>Why? </p><p>It&#8217;s not because the bank is lazy. It&#8217;s not because we lost the source code. </p><p>It is because the fundamental architecture of modern programming languages is hostile to the requirements of global finance.</p><p>You are not fighting code, you are fighting how computers do math.</p><h2>The Math Problem (IEEE 754)</h2><p>When you write <code>float</code> or <code>double</code> in Java, Python, C++, or Go, you are using <strong><a href="https://en.wikipedia.org/wiki/IEEE_754">IEEE 754 Binary Floating Point</a></strong> arithmetic. </p><p>This standard is designed for scientific calculation, measuring the distance to a star or the velocity of a particle. </p><p>It prioritizes range and speed over absolute precision.</p><h3>The Rounding Error</h3><p>Open your browser console or a Node.js shell and type</p><pre><code><code>0.1 + 0.2
// The result: 0.30000000000000004</code></code></pre><p>In a physics simulation, that <code>0.00000000000000004</code> is noise. </p><p>In a banking ledger processing trillions of dollars a day, that error is a regulatory violation, a failed audit, and potentially a lawsuit.</p><h3>Fixed-Point Decimal (COBOL Way)</h3><p>COBOL was not designed for science. </p><p>It was designed for Business (Common Business Oriented Language). </p><p>It does not use Binary Floating Point for money. It uses <strong><a href="https://en.wikipedia.org/wiki/Fixed-point_arithmetic">Fixed-Point arithmetic</a> </strong>stored as<strong> <a href="https://en.wikipedia.org/wiki/Binary-coded_decimal">Binary-Coded Decimal (BCD)</a></strong>.</p><p>In COBOL, you define a variable like this</p><pre><code><code>01 ACCOUNT-BALANCE PIC S9(13)V99 COMP-3.</code></code></pre><ul><li><p><code>01</code>: <strong>Level Number</strong>. In COBOL, <code>01</code> represents a top-level record or variable. Think of it like <code>const</code> or <code>let</code> at the root scope.</p></li><li><p><code>ACCOUNT-BALANCE</code>: The <strong>Variable Name</strong>. (COBOL uses kebab-case because it was invented before snake_case or camelCase won the war).</p></li><li><p><code>PIC</code>: <strong>Picture Clause</strong>. This tells the compiler exactly what the data looks like.</p></li><li><p><code>S</code>: <strong>Signed</strong>. This bit tracks if the number is positive or negative.</p></li><li><p><code>9(13)</code>: <strong>Numeric Integers</strong>. The number <code>9</code> represents a digit. <code>(13)</code> means &#8220;allocate space for 13 of them.&#8221;</p></li><li><p><code>V</code>: <strong>Virtual Decimal</strong>. This is the magic. It tells the CPU &#8220;assume a decimal point here,&#8221; but it <em>does not store a dot character</em> in memory. It saves space.</p></li><li><p><code>99</code>: <strong>Precision</strong>. Allocate exactly 2 digits for cents.</p></li><li><p><code>COMP-3</code>: <strong>Packed Decimal (BCD)</strong>. This is the instruction to store 2 digits per byte (using 4 bits each), rather than the standard 1 byte per character. This is what enables the hardware math precision.</p></li></ul><p>When COBOL calculates <code>0.1 + 0.2</code>, it does not convert them to binary approximations. </p><p>It calculates them in base-10, digit by digit, often utilizing specific hardware instructions on the mainframe (Decimal Floating Point units) that x86 architectures have historically lacked or emulated poorly. </p><p>The result is exactly <code>0.3</code>. Always.</p><h3>The Cost of Emulation</h3><p>You must be wondering can&#8217;t we do this in Java? </p><p>Yes, using <code>java.math.BigDecimal</code>.</p><p>But <code>BigDecimal</code> is a software object. It adds memory overhead and CPU cycles for every single calculation. </p><p>COBOL operates on money at the instruction-set level. When you are processing 50,000 transactions per second (TPS), that overhead isn&#8217;t just a performance hit.</p><p>It&#8217;s an infrastructure bill.</p><h2>True Transactionality (The CICS)</h2><p>The second reason rewrites fail is the misunderstanding of &#8220;Transactionality.&#8221;</p><p>Modern web development is obsessed with &#8220;Statelessness.&#8221; </p><p>You send a REST request, the server forgets you, and you send another. </p><p>State is hard.</p><p>The Mainframe world runs on <strong>CICS</strong> (Customer Information Control System). CICS is an application server that manages transactions with <strong>ACID</strong> properties (Atomicity, Consistency, Isolation, Durability) as a law of physics.</p><p>Lets take an example of ATM withdrawal</p><ol><li><p>Check Balance.</p></li><li><p>Debit Ledger.</p></li><li><p>Dispense Cash.</p></li><li><p>Log Audit Trail.</p></li></ol><p>In CICS, if step 3 fails (the cash jams), the entire transaction rolls back instantly. The ledger is never touched. </p><p>The state remains consistent. </p><h3>The Microservices Nightmare</h3><p>In a distributed microservices architecture, you break these steps into different services.</p><ul><li><p>Service A (Ledger) debits the account.</p></li><li><p>Service B (ATM) fails to dispense.</p></li><li><p>Now Service A must &#8220;compensate&#8221; (undo) the transaction.</p></li></ul><p>You have moved from immediate consistency to <strong>Eventual Consistency</strong>. </p><p>You are now managing &#8220;Distributed Transactions&#8221; and &#8220;Sagas.&#8221;</p><p>So question to you is, do you want your checking account balance to be &#8220;Eventually Consistent&#8221;? </p><p>Or do you want it to be Correct?</p><h2>Scale Up vs. Scale Out</h2><p>The philosophy of the modern cloud is <strong>Scale Out</strong>.</p><p><em>&#8220;If the server is overloaded, spin up 100 more cheap nodes. If a node fails, kill it and retry.&#8221;</em></p><p>The philosophy of the Mainframe is <strong>Scale Up</strong>.</p><p><em>&#8220;This single machine will process everything. It will not fail. If a CPU dies, a backup CPU takes over without the operating system even noticing.&#8221;</em></p><p>Mainframes utilize specialized <strong>I/O Processors</strong> (Channel Subsystems). </p><p>The main CPU doesn&#8217;t waste time reading from a disk or talking to the network card. It delegates that to a sub-processor and keeps crunching numbers. This allows mainframes to run at 100% CPU utilization for years without throttling. </p><p>Try running a Linux server at 100% CPU for an hour, it will become unresponsive.</p><p>Finally, the verdict is</p><ul><li><p>For Twitter, Scale Out. If a tweet fails to load, nobody loses money.</p></li><li><p>For the Global Economy, Scale Up. Reliability is not optional.</p></li></ul><h2>Why this matters to You?</h2><p>Even if you never touch a line of COBOL, the principles of the Mainframe apply to your modern stack.</p><h3>Never Use Floats for Money</h3><p>If you are building a FinTech app in JavaScript or Python, do not use standard number types for currency.</p><p><code>const price = 19.99; // </code>Is Wrong</p><p>Use libraries like <code>decimal.js</code>, Python&#8217;s <code>decimal</code> module, or store values as Integers (cents) and format them only for display </p><p>(<code>const priceInCents = 1999;</code>)</p><h3>Respect the Monolith</h3><p>We have been trained to think &#8220;Microservices = Good&#8221; and &#8220;Monolith = Bad.&#8221;</p><p>But if your application requires strict ACID compliance (inventory management, voting systems, banking), a well-structured Monolith with a single database transaction is infinitely less buggy than a distributed system trying to coordinate state across ten services.</p><h3>&#8220;Legacy&#8221; is a Success Metric</h3><p>Code becomes &#8220;legacy&#8221; only if it survives. </p><p>If you are looking at a system that has been running for 30 years, do not mock it. </p><p>Learn from it. It has survived market crashes, leap years, and user stupidity for decades. </p><p>It is doing something right.</p><div><hr></div><h2>Conclusion</h2><p>Rewriting a Core Banking System is rarely a &#8220;refactoring&#8221; effort. It is an archaeological excavation.</p><p>That &#8220;ugly&#8221; COBOL code contains 40 years of edge cases, the tax law change of 1992, the negative interest rate handling of 2015, the specific rounding rule required by the Bank of Japan.</p><p>If you rewrite it, you will miss these rules. </p><p>You will introduce bugs that were solved in 1985.</p><p>Don&#8217;t replace the Mainframe. Modernize it.</p><p>Wrap the COBOL logic in REST APIs (using Z/OS Connect). </p><p>Let the Java frontend look pretty, but let the Iron down in the basement handle the math.</p><p>Respect the Old Gods. </p><p>They are still holding up the sky.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.binarybox.org/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">Thanks for reading BinaryBox! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Thought - Why Abstract Syntax Tree (AST) makes sense for AI Code Migration]]></title><description><![CDATA[Large Language Models are probabilistic text generators. They are not compilers. They do not possess an underlying, deterministic model of the code they are ingesting.]]></description><link>https://www.binarybox.org/p/thought-why-abstract-syntax-tree</link><guid isPermaLink="false">https://www.binarybox.org/p/thought-why-abstract-syntax-tree</guid><dc:creator><![CDATA[Ashok Vishwakarma]]></dc:creator><pubDate>Tue, 10 Mar 2026 06:01:04 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!kF3a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba79a375-7367-4eff-8668-f2f8ca435fcf_1001x489.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_!kF3a!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba79a375-7367-4eff-8668-f2f8ca435fcf_1001x489.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!kF3a!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba79a375-7367-4eff-8668-f2f8ca435fcf_1001x489.jpeg 424w, https://substackcdn.com/image/fetch/$s_!kF3a!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba79a375-7367-4eff-8668-f2f8ca435fcf_1001x489.jpeg 848w, https://substackcdn.com/image/fetch/$s_!kF3a!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba79a375-7367-4eff-8668-f2f8ca435fcf_1001x489.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!kF3a!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba79a375-7367-4eff-8668-f2f8ca435fcf_1001x489.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!kF3a!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba79a375-7367-4eff-8668-f2f8ca435fcf_1001x489.jpeg" width="1001" height="489" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ba79a375-7367-4eff-8668-f2f8ca435fcf_1001x489.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:489,&quot;width&quot;:1001,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:92486,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!kF3a!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba79a375-7367-4eff-8668-f2f8ca435fcf_1001x489.jpeg 424w, https://substackcdn.com/image/fetch/$s_!kF3a!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba79a375-7367-4eff-8668-f2f8ca435fcf_1001x489.jpeg 848w, https://substackcdn.com/image/fetch/$s_!kF3a!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba79a375-7367-4eff-8668-f2f8ca435fcf_1001x489.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!kF3a!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba79a375-7367-4eff-8668-f2f8ca435fcf_1001x489.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>Right now, in boardrooms and daily stand-ups across the world, executives are signing off on millions for &#8220;AI Modernization,&#8221; while engineers are blindly feeding legacy scripts into ChatGPT to refactor core business logic. </p><p>The pitch is intoxicatingly simple, take a 10,000-line C++ monolith, paste it into an LLM window, and ask it to output pristine, idiomatic Python, Go or Rust microservices.</p><p>This is not engineering. This is reckless gambling.</p><p>The fundamental flaw in this strategy, whether you are a VP buying an enterprise AI tool or a Senior Engineer writing a migration script, is a misunderstanding of what an LLM actually is. </p><p>Large Language Models are probabilistic text generators. They are not compilers. They do not possess an underlying, deterministic model of the code they are ingesting. They do not mathematically understand state mutation, variable shadowing, or lexical scope. </p><p>They simply predict the next most likely token based on latent space vectors.</p><p>An LLM might translate a complex legacy <code>while</code> loop correctly 99 times. But on the 100th time, distracted by a weirdly named variable or an obscure GOTO statement, it will silently hallucinate. It will drop a crucial state mutation. It will misinterpret the lexical scope of a nested variable.</p><p>When you are migrating a critical system such as, a core banking ledger or a flight control system, a 99% success rate is another term for a catastrophic production outage.</p><p>Let&#8217;s look at an example of how a pure LLM migration breaks. </p><p>Smart LLMs rarely make basic syntax errors anymore, instead, they make <strong>semantic errors</strong> by translating text perfectly while fundamentally changing how the computer manages memory which we will see in the example below</p><p>Imagine a pricing calculation in legacy C++ using a <code>struct</code>. By default, C++ passes structs by <em>value</em> (meaning it creates a safe copy).</p><pre><code><code>struct Trade { 
    double price; 
};

// Passed by VALUE. Modifies a local copy for a "what-if" simulation.
void simulateDiscount(Trade t) { 
    t.price *= 0.9; 
    logSimulation("Discounted price would be: ", t.price);
}

// ... elsewhere in the system ...
Trade myTrade = { 100.0 };
simulateDiscount(myTrade);

// myTrade.price is STILL 100.0 here. The original is safely untouched.
processPayment(myTrade); // Processes the actual, full price.</code></code></pre><p>An engineer pastes this into an LLM and asks for an &#8220;idiomatic Python&#8221; translation. The LLM confidently spits out beautifully formatted Python</p><pre><code><code>class Trade:
    def __init__(self, price: float):
        self.price = price

# Passed by REFERENCE. Modifies the original object!
def simulate_discount(t: Trade):
    t.price *= 0.9
    log_simulation("Discounted price would be: ", t.price)

# ... elsewhere in the system ...
my_trade = Trade(100.0)
simulate_discount(my_trade)

# my_trade.price is now 90.0! 
process_payment(my_trade) 
# You just undercharged the client by 10% because of a simulation!</code></code></pre><p>The LLM got a 100% on the syntax. The code is highly readable. </p><p><strong>But it completely corrupted your ledger.</strong> </p><p>The LLM didn&#8217;t know <em>why</em> this was wrong because it doesn&#8217;t build a memory execution graph. It mapped a C++ function signature to a Python function signature. It completely failed to realize it just changed a safe, immutable pass-by-value operation into a highly destructive pass-by-reference mutation.</p><h2>Why AST matters</h2><p>To translate code safely, we have to return to Computer Science 101. </p><p>Code is not text. Treating code as a string of characters is the original issue of pure-LLM migration.</p><p>Code is a tree. Specifically, it is an <strong>Abstract Syntax Tree (AST)</strong>.</p><p>When a traditional compiler reads your code, the very first thing it does is strip away the formatting, the whitespace, and the text, converting the logic into a strict, hierarchical graph of nodes and edges.</p><p>If we parse our legacy C++ <code>simulateDiscount(Trade t)</code> function into an AST, the parser generates a structural map that looks something like this</p><pre><code><code>{
  "node_type": "FunctionDeclaration",
  "identifier": "simulateDiscount",
  "parameters": [
    {
      "node_type": "Parameter",
      "identifier": "t",
      "data_type": "Trade",
      "memory_model": "PASS_BY_VALUE" // &lt;-- The Lifesaver
    }
  ],
  "body": [ ... ]
}</code></code></pre><p>Notice the <code>memory_model</code> metadata. </p><p>The AST isn&#8217;t guessing based on text patterns, it mathematically <em>knows</em> that this specific C++ language construct creates a local copy.</p><p>When an AST-driven migration maps this to Python, it compares the source memory model (<code>PASS_BY_VALUE</code>) to the target language&#8217;s default memory model (in Python, objects are passed by reference).</p><p>Because it detects this mismatch, the structural translation engine intervenes <em>before</em> the LLM can make a mistake. </p><p>It physically forces a constraint into the generated Python code to preserve the semantic contract of the original architecture. </p><p>The resulting code structurally generated by the tool will look like this</p><pre><code><code>import copy

def simulate_discount(t: Trade):
    # AST-enforced safety boundary to preserve C++ pass-by-value
    t_local = copy.copy(t) 
    t_local.price *= 0.9
    log_simulation("Discounted price would be: ", t_local.price)</code></code></pre><p>A pure LLM drops the constraint because it just sees words. </p><p>An AST preserves the constraint because it enforces mathematical logic. </p><p>Probabilistic models guess. ASTs prove.</p><h2>The Hybrid approach</h2><p>If pure LLMs are dangerous, and pure AST translation (source-to-source compilers/transpilers) produces ugly, unmaintainable &#8220;machine code,&#8221; what is the solution?</p><p>If you are building an enterprise-grade migration tool, like the local AI agent architectures we build at BinaryBox, you must use a hybrid pipeline. You do not ask the AI to write code from scratch. You force it to operate within a deterministic pipeline</p><h3>Parse</h3><p>Use a traditional, deterministic parser (like Tree-sitter) to generate the AST of the legacy C++, or Java codebase. </p><p>This locks the exact structure, memory model, and control flow into a mathematical graph.</p><h3>Analyze</h3><p>Pass specific, isolated subtrees of the AST to the LLM. </p><p>Instead of asking the AI to &#8220;rewrite this file,&#8221; you ask it to identify <em>intent</em>.</p><p> <em>&#8220;Analyze this AST node block. Is this an implementation of a bubble sort? Is this a deprecated synchronous network call?&#8221;</em></p><h3>Generate</h3><p>Use the AST to deterministically generate the new syntax, utilizing the LLM only to provide modern idiomatic mapping. </p><p>As shown above, if the AST dictates a pass-by-value parameter, the LLM is constrained to generating code that enforces a clone or copy in the target language.</p><p>The AST guarantees the <em>structure</em>. The AI translates the <em>semantics</em>.</p><h2>Why you should care?</h2><p>Why does this architectural distinction matter to a CTO? </p><p>Because of QA costs.</p><p>If you use a pure LLM to translate a 500,000-line monolith, you cannot trust the output. </p><p>Because the system is probabilistic, human Senior Engineers must manually read, verify, and test <em>every single line</em> of the generated code to ensure no silent bugs were introduced.</p><p>The time and salary cost of having a Principal Engineer QA 500,000 lines of AI-generated spaghetti is often <em>higher</em> than the cost of having them rewrite it by hand. </p><p>The ROI of the migration drops to zero.</p><p>An AST+AI hybrid approach mathematically guarantees structural equivalence. </p><p>If the AST parser proves that all control flows and state mutations have been preserved in the new language, your engineers do not need to read every line. </p><p>They only need to review the architectural patterns and idiomatic choices.</p><p>You eliminate the operational risk of silent logic drops, and you cut the migration timeline from years to months.</p><div><hr></div><h2>Conclusion</h2><p>There is a recurring theme in resilient system design, <strong>Architecture requires constraints.</strong></p><p>We saw this in the Editor Wars. Atom gave developers total freedom to touch the DOM, resulting in chaotic performance. VS Code built a strict Extension Host, a structural prison that constrained plugins and guaranteed a flawless user experience.</p><p>AI agents are no different. If you give an LLM the freedom to write whatever text it wants, it will eventually write a bug that bankrupts your company.</p><p>To do a reliable AI code migration, you must build a structural prison. </p><p>The Abstract Syntax Tree (AST) is that prison. You lock the LLM inside the boundaries of the AST, forcing it to translate node-by-node, bounded by the laws of lexical scope, memory models, and control flow.</p><p>Freedom is chaos. Constraints are reliability. </p><p>Stop trying to use a magic wand, and start building a compiler.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.binarybox.org/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">Thanks for reading BinaryBox! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Deep Dive - How Kafka hit 1 Million write per second on a $40 HDD]]></title><description><![CDATA[Not NVMe. Not even SATA SSDs. Actual magnetic platters with mechanical arms. The kind of physical, spinning rust drives you can buy for $40 at Amazon.]]></description><link>https://www.binarybox.org/p/deep-dive-how-kafka-hit-1-million</link><guid isPermaLink="false">https://www.binarybox.org/p/deep-dive-how-kafka-hit-1-million</guid><dc:creator><![CDATA[Ashok Vishwakarma]]></dc:creator><pubDate>Thu, 05 Mar 2026 06:01:47 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!uE17!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a5fb744-89e6-4560-80d1-bebb8f74af95_1200x628.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_!uE17!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a5fb744-89e6-4560-80d1-bebb8f74af95_1200x628.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uE17!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a5fb744-89e6-4560-80d1-bebb8f74af95_1200x628.jpeg 424w, https://substackcdn.com/image/fetch/$s_!uE17!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a5fb744-89e6-4560-80d1-bebb8f74af95_1200x628.jpeg 848w, https://substackcdn.com/image/fetch/$s_!uE17!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a5fb744-89e6-4560-80d1-bebb8f74af95_1200x628.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!uE17!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a5fb744-89e6-4560-80d1-bebb8f74af95_1200x628.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uE17!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a5fb744-89e6-4560-80d1-bebb8f74af95_1200x628.jpeg" width="1200" height="628" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9a5fb744-89e6-4560-80d1-bebb8f74af95_1200x628.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:628,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;A Guide to Setup a Kafka Environment | Mitrais&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="A Guide to Setup a Kafka Environment | Mitrais" title="A Guide to Setup a Kafka Environment | Mitrais" srcset="https://substackcdn.com/image/fetch/$s_!uE17!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a5fb744-89e6-4560-80d1-bebb8f74af95_1200x628.jpeg 424w, https://substackcdn.com/image/fetch/$s_!uE17!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a5fb744-89e6-4560-80d1-bebb8f74af95_1200x628.jpeg 848w, https://substackcdn.com/image/fetch/$s_!uE17!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a5fb744-89e6-4560-80d1-bebb8f74af95_1200x628.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!uE17!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9a5fb744-89e6-4560-80d1-bebb8f74af95_1200x628.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>In my previous Deep Dive, I tried to write 1,000,000 records per second to PostgreSQL running on an AWS c8g.48xlarge instance backed by Provisioned IOPS SSDs (io2 Block Express).</p><p>The database locked up. The queue depth exploded. The disk, a $30,000/month NVMe SSD simply couldn&#8217;t physically accept the write signals fast enough. </p><p>We had to abandon persistent storage entirely and switch to a Redis cluster. </p><p>We traded durability for speed, accepting that a power failure would vaporize millions of transactions in an instant.</p><p>But here&#8217;s the part that breaks most engineers&#8217; mental models</p><p><strong>Apache Kafka handles 1 million writes per second on cheap, spinning hard drives. </strong></p><p>Not NVMe. Not even SATA SSDs. Actual magnetic platters with mechanical arms. The kind of physical, spinning rust drives you can buy for $40 at Amazon.</p><p>How is this possible?</p><p>The answer isn&#8217;t &#8220;Kafka is written in a faster language&#8221; (it runs on the JVM, which is notoriously heavy). </p><p>The answer isn&#8217;t &#8220;Kafka uses better compression.&#8221;</p><p>The answer is physics.</p><p>Kafka doesn&#8217;t fight the hard drive. It exploits it. This is the story of how Kafka &#8220;cheats&#8221; by respecting the fundamental constraints of hardware, while traditional databases try to bend reality and lose.</p><h2>RAM is Fast, Disk is Slow?</h2><p>Every engineer &#8220;knows&#8221; RAM is faster than disk. But at scale, throughput beats latency. Sequential disk can outrun random RAM.</p><p>Let&#8217;s challenge the conventional wisdom directly. We are all taught these standard latency numbers</p><ul><li><p><strong>RAM</strong> ~100 nanoseconds access time</p></li><li><p><strong>SSD</strong> ~100 microseconds access time (1,000x slower)</p></li><li><p><strong>HDD</strong> ~10 milliseconds access time (100,000x slower)</p></li></ul><p>These numbers are factually correct. But for high-throughput workloads, they are completely irrelevant. The missing context in that table is <strong>Random vs. Sequential I/O</strong>.</p><p>Those latency numbers assume random access, your application is jumping to arbitrary memory addresses or disk sectors. </p><p>But when you switch to sequential access, the story completely flips.</p><p>Let&#8217;s look at Sequential Read/Write Throughput</p><ul><li><p><strong>RAM (DDR4)</strong> ~20-50 GB/sec</p></li><li><p><strong>NVMe SSD</strong> ~3-7 GB/sec</p></li><li><p><strong>SATA SSD</strong> ~500 MB/sec</p></li><li><p><strong>7200 RPM HDD </strong>~200 MB/sec</p></li></ul><p>Here is the key insight. </p><p>A standard, cheap hard drive doing pure sequential I/O can easily saturate a 1 Gbps network link. If your system bottleneck is network throughput (which it absolutely is at 1,000,000 requests per second), the magnetic disk is actually fast enough.</p><p>Let&#8217;s look at the real comparison between our failed experiment and Kafka&#8217;s architecture.</p><h3>Postgres doing 1M random inserts</h3><p>Each insert updates multiple B-Tree indexes. Each index update requires seeking to a random page on the disk. Even on an enterprise SSD, a random seek takes ~100 microseconds. </p><p><code>1,000,000 random seeks &#215; 100 microseconds = 100 seconds of pure seek time. </code></p><p>It is mathematically impossible to process that in one second.</p><h3>Kafka doing 1M sequential appends</h3><p>Kafka writes to the end of a log file. There is no seeking. A modern hard drive sequentially writes at ~200 MB/sec.</p><p><code>1,000,000 writes &#215; 1KB each = 1 GB.</code></p><p>At sequential speeds, that takes roughly <strong>5 seconds</strong> on a single cheap disk, and is trivially parallelized across 5-10 disks in a JBOD (Just a Bunch of Disks) configuration to handle it in 1 second.</p><p>The lesson here. Sequential disk beats random RAM when throughput matters more than latency. </p><p>This is why Kafka doesn&#8217;t need NVMe. It just needs sequential access patterns.</p><blockquote><p>What&#8217;s the throughput of your production database doing sequential scans vs. indexed lookups? If you don&#8217;t know, you&#8217;re optimizing blind.</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_!zkN9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb96c0252-3b11-400a-b5c5-9709772792bc_2816x1536.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!zkN9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb96c0252-3b11-400a-b5c5-9709772792bc_2816x1536.png 424w, https://substackcdn.com/image/fetch/$s_!zkN9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb96c0252-3b11-400a-b5c5-9709772792bc_2816x1536.png 848w, https://substackcdn.com/image/fetch/$s_!zkN9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb96c0252-3b11-400a-b5c5-9709772792bc_2816x1536.png 1272w, https://substackcdn.com/image/fetch/$s_!zkN9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb96c0252-3b11-400a-b5c5-9709772792bc_2816x1536.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!zkN9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb96c0252-3b11-400a-b5c5-9709772792bc_2816x1536.png" width="1456" height="794" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b96c0252-3b11-400a-b5c5-9709772792bc_2816x1536.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:794,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:7498061,&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://www.binarybox.org/i/189540105?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb96c0252-3b11-400a-b5c5-9709772792bc_2816x1536.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_!zkN9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb96c0252-3b11-400a-b5c5-9709772792bc_2816x1536.png 424w, https://substackcdn.com/image/fetch/$s_!zkN9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb96c0252-3b11-400a-b5c5-9709772792bc_2816x1536.png 848w, https://substackcdn.com/image/fetch/$s_!zkN9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb96c0252-3b11-400a-b5c5-9709772792bc_2816x1536.png 1272w, https://substackcdn.com/image/fetch/$s_!zkN9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb96c0252-3b11-400a-b5c5-9709772792bc_2816x1536.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>How Kafka Enforces Sequential I/O</h2><p>Unlike relational databases, which rely heavily on B-Trees to enable fast random lookups, Kafka is built around a single, aggressively simple data structure. <strong>The Commit Log</strong>.</p><p>When a message arrives at a Kafka broker, the system does exactly one thing, it appends the message to the end of the current log segment (a raw file on disk).</p><ul><li><p>It never updates existing entries.</p></li><li><p>It never seeks backward to modify a state.</p></li><li><p>It writes in large batches (saving multiple messages in a single system call).</p></li></ul><p>Why does this work so perfectly?</p><p>Hard drives have a mechanical read/write head. To read or write data, that head must physically move across the platter to find the correct sector. </p><p>This is why random I/O is so devastatingly slow, the mechanical arm is constantly repositioning. It is physically vibrating.</p><p>But when you strictly append to the end of a file, the head drops into position and stays there. The disk controller can stop worrying about seek times and optimize entirely for pure throughput. </p><p>You are essentially turning a hard drive into a firehose.</p><p>If you add batching, writing 100 messages per <code>write()</code> syscall instead of 1, you reduce the CPU context-switch overhead by 100x while keeping the disk arm perfectly still.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CKxA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc022f59d-3413-46ca-88f3-434a6bb7819e_2816x1536.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CKxA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc022f59d-3413-46ca-88f3-434a6bb7819e_2816x1536.png 424w, https://substackcdn.com/image/fetch/$s_!CKxA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc022f59d-3413-46ca-88f3-434a6bb7819e_2816x1536.png 848w, https://substackcdn.com/image/fetch/$s_!CKxA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc022f59d-3413-46ca-88f3-434a6bb7819e_2816x1536.png 1272w, https://substackcdn.com/image/fetch/$s_!CKxA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc022f59d-3413-46ca-88f3-434a6bb7819e_2816x1536.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CKxA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc022f59d-3413-46ca-88f3-434a6bb7819e_2816x1536.png" width="1456" height="794" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c022f59d-3413-46ca-88f3-434a6bb7819e_2816x1536.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:794,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:8293945,&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://www.binarybox.org/i/189540105?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc022f59d-3413-46ca-88f3-434a6bb7819e_2816x1536.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_!CKxA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc022f59d-3413-46ca-88f3-434a6bb7819e_2816x1536.png 424w, https://substackcdn.com/image/fetch/$s_!CKxA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc022f59d-3413-46ca-88f3-434a6bb7819e_2816x1536.png 848w, https://substackcdn.com/image/fetch/$s_!CKxA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc022f59d-3413-46ca-88f3-434a6bb7819e_2816x1536.png 1272w, https://substackcdn.com/image/fetch/$s_!CKxA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc022f59d-3413-46ca-88f3-434a6bb7819e_2816x1536.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><h3>The Trade-off Kafka Makes</h3><p>Databases optimize for flexibility, random access (<em>give me record ID 47293</em>), updates in place (<em>change this user&#8217;s email</em>), and complex queries (<em>JOIN across three tables</em>).</p><p>Kafka completely abandons this. It optimizes strictly for append-only writes (<em>add this event</em>), sequential reads (<em>replay messages in order</em>), and time-based queries (<em>give me all events from 2:00 PM</em>).</p><p>This is a conscious architectural choice, not magic. By refusing to support random updates, Kafka gets to use the fastest possible I/O pattern the hardware offers.</p><p>Look at Netflix. They log every single user interaction (play, pause, seek, stop) to Kafka. At peak, that is hundreds of thousands of events per second from millions of concurrent users. </p><p>Netflix doesn&#8217;t need to query &#8220;what did user X do exactly 4 seconds ago?&#8221; in real-time. They need to capture the firehose of data and process it asynchronously. </p><p>A B-Tree database would collapse under that write load. Kafka&#8217;s append-only log absorbs it effortlessly.</p><blockquote><p><strong>Look at your highest-volume write workload.</strong> </p><p>Is it actually appending events, or are you using INSERT/UPDATE simply because &#8220;that&#8217;s what databases do&#8221;?</p></blockquote><h2>Kafka Doesn&#8217;t Manage Memory</h2><p>If you write a standard application that interacts with a disk and a network, your data flow generally looks like this</p><ol><li><p>Read data from disk into a kernel buffer.</p></li><li><p>Copy data from the kernel buffer to application memory (like the JVM heap).</p></li><li><p>Process the data.</p></li><li><p>Copy data from application memory back to a kernel socket buffer.</p></li><li><p>Write to the network socket.</p></li></ol><p>At extreme throughput, this standard pattern creates two massive system bottlenecks.</p><h4>1. Garbage Collection Death</h4><p>Every message object allocated in the JVM heap must eventually be garbage collected. </p><p>If you are pushing 1,000,000 messages per second through application memory, the Garbage Collector cannot keep up. </p><p>You will experience massive &#8220;stop-the-world&#8221; pauses that instantly kill your throughput and trigger network timeouts.</p><h4>2. Double Buffering</h4><p>Your data exists in two places at once, kernel memory (the OS page cache) and application memory (the JVM heap). </p><p>You are wasting RAM, and more importantly, you are wasting CPU cycles copying the exact same bytes back and forth between user space and kernel space.</p><h3>Kafka&#8217;s Solution</h3><p><strong>Bypass Application Memory Entirely.</strong></p><p>Kafka does not attempt to manage a complex internal buffer pool. It relies entirely on the Linux OS Page Cache.</p><p>When Kafka writes a message, it calls <code>write()</code> to append to the log file. The OS buffers this write in the page cache in RAM. Kafka immediately returns a success acknowledgment to the producer. </p><p>The Linux kernel flushes that page cache to the physical disk asynchronously in the background.</p><p>When Kafka reads a message, the OS loads the file into the page cache. Kafka references the page cache directly. The message data is never copied into the JVM heap. Therefore, there is no garbage collection penalty.</p><p>Modern operating systems are ruthlessly efficient at managing file caches. Linux will gladly use 100% of your free RAM as a page cache. Kafka doesn&#8217;t try to outsmart the OS, it defers to the kernel.</p><p>The practical result? </p><p>A Kafka broker with 64 GB of RAM effectively has ~4 GB dedicated to the JVM heap (which is tiny), and ~60 GB dedicated to the OS page cache. </p><p>Consumers reading recent data get RAM-speed access because the OS serves it directly from the cache. Older messages fall out of cache and are read from disk, but because it&#8217;s sequential, it remains incredibly fast.</p><p>Postgres must manage its own complex buffer pool because it supports random updates, ACID transactions, and row-level locking. </p><p>Kafka can rely entirely on the OS because it only does sequential access.</p><h2>Zero-Copy</h2><p>This brings us to the centerpiece of Kafka&#8217;s architecture.</p><p>The fastest code is the code that never runs. Zero-Copy means the CPU doesn&#8217;t touch your data. </p><p>That&#8217;s why it&#8217;s fast.</p><h3>The Traditional Data Path (4 Copies)</h3><p>When a consumer requests a batch of messages from Kafka, a naive implementation would execute the following path</p><ol><li><p><strong>Disk &#8594; Kernel Buffer -</strong> Via DMA - Direct Memory Access. Hardware does the work.</p></li><li><p><strong>Kernel Buffer &#8594; Application Buffer -</strong> CPU copies data from kernel space into the Kafka JVM heap.</p></li><li><p><strong>Application Buffer &#8594; Socket Buffer -</strong> CPU copies data from the JVM back to the kernel network stack.</p></li><li><p><strong>Socket Buffer &#8594; NIC -</strong> Via DMA to the Network Interface Card.</p></li></ol><p>At each copy boundary, you suffer. CPU cycles are wasted. You force expensive context switches between user space and kernel space. You pollute the CPU L1/L2 caches, evicting hot application state just to make room for transient message bytes that are passing through.</p><p>At scale, serving 1,000,000 messages/sec means copying 1 GB/sec <em>four times</em>. That is 4 GB/sec of memory bandwidth consumed just moving the exact same bytes around the motherboard. </p><p>On our massive c8g.48xlarge server, the CPU would be saturated just copying data, doing absolutely zero actual processing.</p><h3>The Zero-Copy Solution</h3><p><code>sendfile() </code>Linux provides the <code>sendfile()</code> syscall (and its cousin <code>splice()</code>) to solve this exact bottleneck.</p><pre><code><code>// Traditional approach (CPU intensive)
read(file_fd, buffer, size);           // Copy from kernel to app
write(socket_fd, buffer, size);        // Copy from app to kernel

// Zero-copy approach (Hardware accelerated)
sendfile(socket_fd, file_fd, offset, size);  // Copy directly kernel-to-kernel</code></code></pre><p>What actually happens under the hood when Kafka uses zero-copy?</p><ol><li><p><strong>Disk &#8594; Kernel Page Cache - </strong>DMA read.</p></li><li><p><strong>Page Cache &#8594; Socket Buffer - </strong> A kernel-to-kernel copy. <strong>User-space is completely bypassed.</strong></p></li><li><p><strong>Socket Buffer &#8594; NIC - </strong>DMA write.</p></li></ol><p>The message data <em>never enters Kafka&#8217;s application memory</em>. Kafka simply issues a command to the Linux kernel, </p><p><em>&#8220;Take 500 bytes from file descriptor Z at offset X, and stream them directly into network socket W.&#8221;</em></p><p>The kernel and the DMA controllers handle 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_!o_bS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc94f8fe4-dad4-4a4e-a2aa-398897675231_2816x1536.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!o_bS!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc94f8fe4-dad4-4a4e-a2aa-398897675231_2816x1536.png 424w, https://substackcdn.com/image/fetch/$s_!o_bS!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc94f8fe4-dad4-4a4e-a2aa-398897675231_2816x1536.png 848w, https://substackcdn.com/image/fetch/$s_!o_bS!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc94f8fe4-dad4-4a4e-a2aa-398897675231_2816x1536.png 1272w, https://substackcdn.com/image/fetch/$s_!o_bS!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc94f8fe4-dad4-4a4e-a2aa-398897675231_2816x1536.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!o_bS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc94f8fe4-dad4-4a4e-a2aa-398897675231_2816x1536.png" width="1456" height="794" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c94f8fe4-dad4-4a4e-a2aa-398897675231_2816x1536.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:794,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:7118821,&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://www.binarybox.org/i/189540105?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc94f8fe4-dad4-4a4e-a2aa-398897675231_2816x1536.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_!o_bS!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc94f8fe4-dad4-4a4e-a2aa-398897675231_2816x1536.png 424w, https://substackcdn.com/image/fetch/$s_!o_bS!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc94f8fe4-dad4-4a4e-a2aa-398897675231_2816x1536.png 848w, https://substackcdn.com/image/fetch/$s_!o_bS!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc94f8fe4-dad4-4a4e-a2aa-398897675231_2816x1536.png 1272w, https://substackcdn.com/image/fetch/$s_!o_bS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc94f8fe4-dad4-4a4e-a2aa-398897675231_2816x1536.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>Instead of 4 copies, you get 2 copies (and both are heavily hardware-accelerated). Instead of 4 expensive context switches, you get 1. Instead of thrashing the CPU cache, you keep it pristine for actual orchestration logic.</p><p><strong><a href="https://www.linkedin.com/blog/engineering/open-source/benchmarking-apache-kafka-2-million-writes-second-three-cheap-machines">LinkedIn engineering published benchmarks</a></strong> demonstrating that zero-copy improves Kafka&#8217;s throughput by 2-3x for consumer reads. At 1M messages/sec, that is the literal difference between needing a cluster of 3 massive servers versus 1 server.</p><h4>Why traditional message queues can&#8217;t do this</h4><p>RabbitMQ, ActiveMQ, and traditional enterprise queues usually transform messages (adding headers, parsing routing keys), encrypt payloads in the application layer, or apply middleware. </p><p>All of these actions require the message to be pulled into application memory so the CPU can inspect and alter the bytes.</p><p>Kafka&#8217;s messages are opaque byte arrays. Kafka does not parse them, it does not transform them, and it does not care about their contents. </p><p>This architectural constraint allows Kafka to use zero-copy. The broker is just a dumb, incredibly fast pipe moving bytes from a disk to a network card.</p><blockquote><p><strong>How many times is your data copied between receiving it and sending it?</strong> Every single copy is CPU waste you are paying for on your AWS bill.</p></blockquote><h2>When to Use This Pattern</h2><p>Understanding how Kafka works is only half the battle. You need to know when to apply these principles, append-only logs and zero-copy transfers to your own systems.</p><h3>This pattern WORKS when</h3><h4>Write-heavy, read-sequential workloads</h4><p>Event logging, audit trails, analytics ingestion pipelines, and background job queues.</p><h4>Messages are opaque blobs</h4><p>You don&#8217;t need the broker to parse, transform, or route based on content. Consumers handle the deserialization.</p><h4>Recent data is hot, old data is cold</h4><p>99% of your reads are for data written in the last few minutes (guaranteeing a page cache hit). Occasional historical reads (requiring a disk seek) are acceptable.</p><h4>Durability matters, but immediate consistency does not</h4><p>Relying on the OS page cache flush (write-behind caching) is &#8220;good enough,&#8221; and you don&#8217;t need to force an <code>fsync()</code> to the physical platter on every single write.</p><h3>This pattern DOES NOT work when</h3><h4>Random access queries</h4><p>&#8220;Give me user 47293&#8217;s profile.&#8221; (Use a traditional database).</p><h4>Low-latency single-message processing</h4><p>If you need sub-millisecond latency per message, Kafka isn&#8217;t the tool. Zero-copy optimizes for massive batch throughput, not single-message latency.</p><h4>Message transformation in the broker</h4><p>If your broker must decrypt, dynamically route, or mutate messages, you cannot use zero-copy because you must pull the data into application memory.</p><p>Before reaching for Postgres, Redis, or MongoDB for a high-volume endpoint, ask yourself</p><p><em>&#8220;Am I appending events, or am I updating records?&#8221;</em> </p><p>If your workload is append-mostly and sequential-read, you are leaving 10x performance on the table by using a general-purpose B-Tree database.</p><p>Consider Kafka for event streams, ClickHouse for analytics, or InfluxDB for time-series metrics. </p><p>All of them use append-only logs. All of them respect sequential I/O.</p><div><hr></div><h2>Conclusion</h2><p>In my 1M RPS test, Postgres failed not because it was poorly designed, but because it was designed for a entirely different problem space.</p><p>Postgres optimizes for maximum flexibility, random updates, complex queries, and strict ACID guarantees. To deliver this flexibility, it must use B-Trees, endure random I/O, and manage its own application buffers.</p><p>Kafka optimizes for maximum throughput, append-only writes, sequential reads, and eventual consistency. To deliver this throughput, it uses commit logs, demands sequential I/O, and relies entirely on kernel-managed caching.</p><p>Neither system is &#8220;better.&#8221; They solve different physical problems.</p><p>The lesson here isn&#8217;t &#8220;use Kafka instead of Postgres.&#8221; </p><p>The lesson is, <strong>understand the physics of your hardware, and then choose the data structure that ruthlessly exploits it.</strong></p><p>Sequential disk is faster than random RAM. Zero-copy is faster than application processing. The Linux OS page cache is smarter than your hand-rolled buffer pool.</p><p>Stop fighting the metal. Start respecting it. When you align your architecture with the strict constraints of the underlying hardware, you don&#8217;t need to scale out to hundreds of servers. You can handle 1 million writes per second on a $40 hard drive.</p><p>That&#8217;s not magic. That&#8217;s engineering.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.binarybox.org/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">Thanks for reading BinaryBox! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Report - How Andres Freund saves the Internet]]></title><description><![CDATA[The backdoor had been planted over 2.5 years by a nation-state actor who earned the trust of the maintainer, contributed legitimate code, and then injected malware into the build process itself.]]></description><link>https://www.binarybox.org/p/report-how-andres-freund-saves-the</link><guid isPermaLink="false">https://www.binarybox.org/p/report-how-andres-freund-saves-the</guid><dc:creator><![CDATA[Ashok Vishwakarma]]></dc:creator><pubDate>Tue, 03 Mar 2026 06:00:15 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!kGkU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30a0e6ff-c853-47a5-a339-ef93e724660b_1920x1080.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_!kGkU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30a0e6ff-c853-47a5-a339-ef93e724660b_1920x1080.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!kGkU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30a0e6ff-c853-47a5-a339-ef93e724660b_1920x1080.png 424w, https://substackcdn.com/image/fetch/$s_!kGkU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30a0e6ff-c853-47a5-a339-ef93e724660b_1920x1080.png 848w, https://substackcdn.com/image/fetch/$s_!kGkU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30a0e6ff-c853-47a5-a339-ef93e724660b_1920x1080.png 1272w, https://substackcdn.com/image/fetch/$s_!kGkU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30a0e6ff-c853-47a5-a339-ef93e724660b_1920x1080.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!kGkU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30a0e6ff-c853-47a5-a339-ef93e724660b_1920x1080.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/30a0e6ff-c853-47a5-a339-ef93e724660b_1920x1080.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2501805,&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://www.binarybox.org/i/189579121?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30a0e6ff-c853-47a5-a339-ef93e724660b_1920x1080.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_!kGkU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30a0e6ff-c853-47a5-a339-ef93e724660b_1920x1080.png 424w, https://substackcdn.com/image/fetch/$s_!kGkU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30a0e6ff-c853-47a5-a339-ef93e724660b_1920x1080.png 848w, https://substackcdn.com/image/fetch/$s_!kGkU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30a0e6ff-c853-47a5-a339-ef93e724660b_1920x1080.png 1272w, https://substackcdn.com/image/fetch/$s_!kGkU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30a0e6ff-c853-47a5-a339-ef93e724660b_1920x1080.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>March 2024. <strong><a href="https://www.linkedin.com/in/andres-freund/">Andres Freund</a></strong>, a Microsoft engineer and PostgreSQL developer, is working from home when he notices something odd.</p><p>His SSH logins are taking 500 milliseconds longer than normal.</p><p>Most engineers would ignore this. Network latency. A busy server. Maybe restart the daemon and forget about it.</p><p>Freund didn&#8217;t. He broke out the profiler and debugged it.</p><p>He traced the micro-delay to <code>liblzma</code>. A ubiquitous compression library used by OpenSSH (via systemd). </p><p>He found that recent versions contained a backdoor so sophisticated that it had bypassed</p><ul><li><p>Automated security scanners</p></li><li><p>Code reviews from major Linux distributions</p></li><li><p>Penetration testing</p></li><li><p>Static analysis tools</p></li><li><p>The &#8220;many eyes&#8221; of the open-source community</p></li></ul><p>The backdoor had been planted over 2.5 years by a nation-state actor who earned the trust of the maintainer, contributed legitimate code, and then injected malware into the build process itself.</p><p>If Freund had ignored that 500ms delay, every major Linux distribution would have shipped SSH servers with a pre-installed, pre-authentication remote access backdoor.</p><p>Every CISO in the world relies on million-dollar security budgets, automated scanners, and penetration tests. A backdoor that took 2.5 years to plant was caught by one engineer who thought, &#8220;Huh, that CPU spike is weird.&#8221;</p><p>This is the story of why your security budget missed what one curious engineer caught by accident. And why &#8220;free&#8221; open-source software might be the most expensive dependency in your infrastructure.</p><h2>The Myth</h2><p>Let&#8217;s challenge the core religion of modern software engineering.</p><p>Linus&#8217;s Law states</p><p><em>&#8220;Given enough eyeballs, all bugs are shallow.&#8221;</em> </p><p>This has been gospel in the tech industry for 30 years. It&#8217;s why enterprise companies confidently build trillion-dollar infrastructures on open-source software. </p><p>The assumption is that open source is inherently more secure than proprietary code because anyone can audit it. Bad actors can&#8217;t hide in plain sight when millions of developers are watching.</p><p>Here is the reality of <strong><a href="https://github.com/tukaani-project/xz">XZ Utils</a></strong></p><ul><li><p><strong>Downloads - </strong>1.4 million per day.</p></li><li><p><strong>Usage - </strong>Core dependency for every major Linux distribution (Debian, Ubuntu, Fedora, Red Hat).</p></li><li><p><strong>Criticality - </strong>Required for SSH authentication on virtually every server on the internet.</p></li><li><p><strong>Maintainers -</strong> ONE unpaid volunteer (<strong><a href="https://github.com/Larhzu">Lasse Collin</a></strong>).</p></li><li><p><strong>Annual Budget -</strong> $0.</p></li><li><p><strong>Last Security Audit -</strong> Never.</p></li></ul><p>According to the Open Source Security and Risk Analysis (OSSRA) report, 87% of commercial applications contain open-source components. </p><p>Yet, less than 3% of organizations perform regular security audits of their dependencies, and the average application relies on 500+ transitive dependencies.</p><p>Linus&#8217;s Law assumes the eyes are looking. But nobody audits compression libraries. Nobody reviews arcane build scripts. Nobody sponsors the maintainer working nights and weekends for zero pay.</p><p>Your production infrastructure runs on code that hasn&#8217;t been reviewed since it was written. The &#8220;many eyes&#8221; aren&#8217;t watching. They&#8217;re assuming someone else is. This collective delusion is exactly what made the XZ attack possible.</p><blockquote><p>How many dependencies does your main application have? How many of those have you personally reviewed in the last year? If the answer is &#8216;zero,&#8217; you&#8217;re trusting strangers with your production environment.</p></blockquote><h2>How Jia Tan Bypassed the Eyeballs</h2><p>To understand why your scanners failed, you have to understand the mechanics of the attack. It was a masterpiece of both social and software engineering.</p><h3>Phase 1 - Social Engineering the Maintainer</h3><p>The attack didn&#8217;t start with code. It started with economics.</p><p>Lasse Collin had maintained XZ Utils alone, unpaid, for over 15 years. He had a full-time job. XZ was his nights-and-weekends project. In 2021, a coordinated pressure campaign began. Multiple sock-puppet accounts created hostile issues on the XZ mailing list</p><ul><li><p><em>&#8220;Lasse is unresponsive to patches.&#8221;</em></p></li><li><p><em>&#8220;This project is effectively unmaintained.&#8221;</em></p></li><li><p><em>&#8220;We need new leadership or XZ will die.&#8221;</em></p></li></ul><p>The manufactured urgency worked. Lasse, burnt out and dealing with personal health issues, accepted help.</p><p>Enter &#8220;Jia Tan&#8221;</p><p>A seemingly legitimate open-source contributor who had been making small, helpful commits for months. Jia earned trust slowly. He fixed real bugs. He responded to issues professionally. He became indispensable. After two years of free labor, Lasse granted Jia Tan co-maintainer status and release access.</p><p>The initial vulnerability wasn&#8217;t a buffer overflow. It was the economics. One unpaid volunteer maintaining critical infrastructure for billions of users. The attackers didn&#8217;t need a zero-day. They just needed patience.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-prN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5bd98d1-9989-40d1-9c64-48d97518e226_2816x1536.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-prN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5bd98d1-9989-40d1-9c64-48d97518e226_2816x1536.png 424w, https://substackcdn.com/image/fetch/$s_!-prN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5bd98d1-9989-40d1-9c64-48d97518e226_2816x1536.png 848w, https://substackcdn.com/image/fetch/$s_!-prN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5bd98d1-9989-40d1-9c64-48d97518e226_2816x1536.png 1272w, https://substackcdn.com/image/fetch/$s_!-prN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5bd98d1-9989-40d1-9c64-48d97518e226_2816x1536.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-prN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5bd98d1-9989-40d1-9c64-48d97518e226_2816x1536.png" width="1456" height="794" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d5bd98d1-9989-40d1-9c64-48d97518e226_2816x1536.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:794,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:6972543,&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://www.binarybox.org/i/189579121?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5bd98d1-9989-40d1-9c64-48d97518e226_2816x1536.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_!-prN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5bd98d1-9989-40d1-9c64-48d97518e226_2816x1536.png 424w, https://substackcdn.com/image/fetch/$s_!-prN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5bd98d1-9989-40d1-9c64-48d97518e226_2816x1536.png 848w, https://substackcdn.com/image/fetch/$s_!-prN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5bd98d1-9989-40d1-9c64-48d97518e226_2816x1536.png 1272w, https://substackcdn.com/image/fetch/$s_!-prN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5bd98d1-9989-40d1-9c64-48d97518e226_2816x1536.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><h3>Phase 2 - Hiding the Payload</h3><p>Traditional malware injection is obvious: You add malicious code to <code>.c</code> source files. But Jia Tan knew code reviewers read source files. Even casual contributors glance at GitHub diffs.</p><p>Jia Tan&#8217;s solution was brilliant. Don&#8217;t hide the backdoor in the source code. Hide it where nobody looks.</p><p>The payload was concealed inside binary test files, specifically, <code>.xz</code> compressed blobs used for the test suite to verify the compressor was working. Developers assume test data is benign. Nobody reviews binary blobs. The malicious test files sat in the repository for months, completely invisible to the human eye.</p><h3>Phase 3 - Build-Time Injection</h3><p>The source code remained clean. Your Veracode or Snyk scanners found nothing suspicious in the <code>.c</code> files. But Jia Tan heavily obfuscated and modified the build scripts (<code>configure.ac</code> and <code>Makefile.am</code>).</p><p>During the <code>make</code> compilation process on a Debian or RPM build serve</p><ol><li><p>The build script extracted the hidden payload from the binary test files.</p></li><li><p>It decrypted the payload and injected the backdoor directly into the compiled binary (<code>liblzma.so</code>).</p></li></ol><p>The source code <em>never</em> contained the malware, it only existed in the build artifact.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ekmx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8879f369-88b9-4b9b-8ff9-022839cebc8f_2816x1536.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ekmx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8879f369-88b9-4b9b-8ff9-022839cebc8f_2816x1536.png 424w, https://substackcdn.com/image/fetch/$s_!ekmx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8879f369-88b9-4b9b-8ff9-022839cebc8f_2816x1536.png 848w, https://substackcdn.com/image/fetch/$s_!ekmx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8879f369-88b9-4b9b-8ff9-022839cebc8f_2816x1536.png 1272w, https://substackcdn.com/image/fetch/$s_!ekmx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8879f369-88b9-4b9b-8ff9-022839cebc8f_2816x1536.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ekmx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8879f369-88b9-4b9b-8ff9-022839cebc8f_2816x1536.png" width="1456" height="794" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8879f369-88b9-4b9b-8ff9-022839cebc8f_2816x1536.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:794,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:8399540,&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://www.binarybox.org/i/189579121?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8879f369-88b9-4b9b-8ff9-022839cebc8f_2816x1536.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_!ekmx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8879f369-88b9-4b9b-8ff9-022839cebc8f_2816x1536.png 424w, https://substackcdn.com/image/fetch/$s_!ekmx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8879f369-88b9-4b9b-8ff9-022839cebc8f_2816x1536.png 848w, https://substackcdn.com/image/fetch/$s_!ekmx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8879f369-88b9-4b9b-8ff9-022839cebc8f_2816x1536.png 1272w, https://substackcdn.com/image/fetch/$s_!ekmx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8879f369-88b9-4b9b-8ff9-022839cebc8f_2816x1536.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><blockquote><p><strong>Your build process is a black box.</strong> </p><p>You review code, but do you verify the compiled binary matches the source? If not, how would you detect a build-time injection?</p></blockquote><h3>Phase 4 - The IFUNC/GOT Hijacking</h3><p>Once the malicious <code>liblzma.so</code> was loaded into memory by the SSH daemon, it executed a sophisticated Linux exploitation technique</p><p><strong>IFUNC (Indirect Function) Resolvers and GOT (Global Offset Table) Hijacking.</strong></p><p>Linux supports IFUNC, a mechanism where a function&#8217;s implementation is chosen dynamically at runtime based on CPU capabilities (e.g., choosing an AVX-512 optimized version if the hardware supports it). </p><p>The backdoor registered a malicious IFUNC resolver that executed during the dynamic linking phase, <em>before</em> <code>main()</code> even runs.</p><p>This resolver modified the Global Offset Table, replacing the pointer to OpenSSH&#8217;s <code>RSA_public_decrypt()</code> function with a pointer to the attacker&#8217;s own code.</p><p>The backdoor allowed remote code execution using a specific Ed448 cryptographic key controlled by the attacker. No valid SSH credentials were required. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!gDY6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7167fb4e-95b2-4eb7-8981-2af07cfc1338_2816x1536.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gDY6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7167fb4e-95b2-4eb7-8981-2af07cfc1338_2816x1536.png 424w, https://substackcdn.com/image/fetch/$s_!gDY6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7167fb4e-95b2-4eb7-8981-2af07cfc1338_2816x1536.png 848w, https://substackcdn.com/image/fetch/$s_!gDY6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7167fb4e-95b2-4eb7-8981-2af07cfc1338_2816x1536.png 1272w, https://substackcdn.com/image/fetch/$s_!gDY6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7167fb4e-95b2-4eb7-8981-2af07cfc1338_2816x1536.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!gDY6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7167fb4e-95b2-4eb7-8981-2af07cfc1338_2816x1536.png" width="1456" height="794" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7167fb4e-95b2-4eb7-8981-2af07cfc1338_2816x1536.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:794,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:6868307,&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://www.binarybox.org/i/189579121?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7167fb4e-95b2-4eb7-8981-2af07cfc1338_2816x1536.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_!gDY6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7167fb4e-95b2-4eb7-8981-2af07cfc1338_2816x1536.png 424w, https://substackcdn.com/image/fetch/$s_!gDY6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7167fb4e-95b2-4eb7-8981-2af07cfc1338_2816x1536.png 848w, https://substackcdn.com/image/fetch/$s_!gDY6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7167fb4e-95b2-4eb7-8981-2af07cfc1338_2816x1536.png 1272w, https://substackcdn.com/image/fetch/$s_!gDY6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7167fb4e-95b2-4eb7-8981-2af07cfc1338_2816x1536.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 was entirely stealthy, it checked if the process was <code>/usr/sbin/sshd</code> so it wouldn&#8217;t crash normal tarball extractions, and it self-destructed if it detected profiling or debugging tools. (It only failed to hide from Freund&#8217;s profiler because of a tiny CPU cycle overhead bug).</p><p>Modern security assumes you can trust the build process. Code review, static analysis, and fuzzing all operate on source code. </p><p>But if the build itself is compromised, none of that matters. This was an attack on the software supply chain, not the software itself.</p><h2>The Root Cause</h2><p>Let&#8217;s shift from the technical to the economic. The brutal math of open-source maintenance is the actual root cause of CVE-2024-3094.</p><p>Let&#8217;s quantify what Lasse Collin was managing</p><ul><li><p><strong>Impact -</strong> Billions of devices worldwide.</p></li><li><p><strong>Critical dependencies -</strong> OpenSSH, systemd, dpkg, rpm.</p></li><li><p><strong>Maintainer compensation -</strong> $0/year.</p></li><li><p><strong>Support burden -</strong> Thousands of emails, bug reports, and feature requests from corporations demanding free support.</p></li></ul><p>The Fortune 500 runs mission-critical infrastructure on a foundation of unpaid labor.</p><ul><li><p><strong>OpenSSL</strong> - Maintained by ~10 people with an Annual Budget of ~$1M (via grants) and used by Billions of users.</p></li><li><p><strong>curl</strong> - Maintained by Daniel Stenberg (mostly solo) with an annual budget of ~100k (sponsors) and used by Billions of users.</p></li><li><p><strong>SQLite</strong> - Maintained by D. Richard Hipp + 2 contractors with a Self-funded budget and used by Billions of users.</p></li><li><p><strong>XZ Utils (pre-attack)</strong> - Maintained by 1 unpaid volunteer with $0 budget and used by Billions of users.</p></li></ul><p>The sock-puppet pressure campaign worked because Lasse was genuinely overwhelmed. The complaints about slow response times were real. &#8220;Helpful&#8221; contributors offered relief, and no one else (not Amazon, not Google, not Microsoft) was stepping up to help him. Handing off maintenance seemed like the responsible thing to 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_!8QXF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88abcdcd-0c14-4c1b-a1a3-03014bcd7227_2816x1536.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8QXF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88abcdcd-0c14-4c1b-a1a3-03014bcd7227_2816x1536.png 424w, https://substackcdn.com/image/fetch/$s_!8QXF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88abcdcd-0c14-4c1b-a1a3-03014bcd7227_2816x1536.png 848w, https://substackcdn.com/image/fetch/$s_!8QXF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88abcdcd-0c14-4c1b-a1a3-03014bcd7227_2816x1536.png 1272w, https://substackcdn.com/image/fetch/$s_!8QXF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88abcdcd-0c14-4c1b-a1a3-03014bcd7227_2816x1536.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8QXF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88abcdcd-0c14-4c1b-a1a3-03014bcd7227_2816x1536.png" width="1456" height="794" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/88abcdcd-0c14-4c1b-a1a3-03014bcd7227_2816x1536.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:794,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:7251510,&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://www.binarybox.org/i/189579121?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88abcdcd-0c14-4c1b-a1a3-03014bcd7227_2816x1536.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_!8QXF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88abcdcd-0c14-4c1b-a1a3-03014bcd7227_2816x1536.png 424w, https://substackcdn.com/image/fetch/$s_!8QXF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88abcdcd-0c14-4c1b-a1a3-03014bcd7227_2816x1536.png 848w, https://substackcdn.com/image/fetch/$s_!8QXF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88abcdcd-0c14-4c1b-a1a3-03014bcd7227_2816x1536.png 1272w, https://substackcdn.com/image/fetch/$s_!8QXF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88abcdcd-0c14-4c1b-a1a3-03014bcd7227_2816x1536.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 XZ Utils disappeared tomorrow and you had to build a replacement in-house, how much would it cost? </p><p>A conservative estimate</p><p><code>3 senior engineers &#215; 2 years &#215; $200K = $1.2 million. </code></p><p>That is the real enterprise value Lasse Collin was providing. For free. While working a separate full-time job.</p><p>Companies will happily pay $50,000 annually for a Datadog license to monitor their infrastructure. </p><p>But they won&#8217;t pay $50,000 to sponsor the unpaid maintainer of the compression library that every server in their data center depends on. Until the maintainer burns out. Hands over access. And a nation-state backdoor ends up in production.</p><blockquote><p>If your most critical open-source dependency disappeared tomorrow, how much would it cost to replace it? That&#8217;s what the maintainer is saving you. Are you paying them anything?</p></blockquote><h2>What you should do now?</h2><p>The era of blind trust in <code>npm install</code> and <code>apt-get upgrade</code> is over. </p><p>Here is the framework for securing your supply chain Monday morning</p><h3>Audit Your Dependency Tree</h3><p>Don&#8217;t just look for known CVEs. Identify <strong>maintenance risk</strong>.</p><ul><li><p>Run dependency analysis (<code>npm audit</code>, <code>pip-audit</code>, <code>cargo audit</code>).</p></li><li><p>Find dependencies with fewer than 3 active maintainers.</p></li><li><p>Check the last commit date (&gt;1 year without activity is a massive red flag).</p></li><li><p><strong>Red Flags - </strong>A single maintainer, hundreds of unresolved issues, or a maintainer posting &#8220;looking for new ownership.&#8221;</p></li></ul><h3>Pin and Vendor Critical Dependencies</h3><p>Stop trusting the internet to compile your software.</p><p>Stop using <code>latest</code> or <code>^1.0.0</code> version ranges in production. Stop auto-updating dependencies without review.</p><p>Pin exact versions with SHA checksums. Use lock files (<code>package-lock.json</code>, <code>Cargo.lock</code>). For ultra-critical infrastructure libraries, <strong>vendor them</strong> (copy the source into your own repository) and build them from source.</p><h3>Zero Trust for the Build Process</h3><p>If the build is compromised, the code review doesn&#8217;t matter.</p><ul><li><p>Implement <strong>Reproducible Builds</strong> (the exact same source code must produce the exact same byte-for-byte binary).</p></li><li><p>Isolate your build environments in ephemeral containers or VMs.</p></li><li><p>Generate a <strong>Software Bill of Materials (SBOM)</strong> for every release.</p></li><li><p>Verify that downloaded packages match published checksums and ensure no unexpected network requests happen during your CI/CD pipeline.</p></li></ul><h3>Fund the Maintainers</h3><p>Funding maintainers isn&#8217;t charity. It&#8217;s cheaper than breach response, cheaper than in-house development, and cheaper than explaining to your board why you ignored supply chain risk.</p><ul><li><p>If a library is critical to your business, sponsor it via GitHub Sponsors, Tidelift, or Open Collective.</p></li><li><p>The Goal - $50K&#8211;$100K/year for infrastructure-level libraries.</p></li><li><p>This reduces maintainer burnout, creates accountability, and gives you input on roadmap and priority bug fixes.</p></li></ul><h3>Treat Open Source Like Vendors</h3><p>Apply the exact same due diligence to your open-source libraries that you apply to a SaaS vendor. Monitor dependencies like production services. Alert on new releases, review changelogs <em>before</em> upgrading, and test updates in staging.</p><p>You cannot audit every line of every dependency. You have 500+ transitive dependencies, and they change constantly. But you CAN control your build process, fund the maintainers of critical libraries, and treat &#8220;free&#8221; software as unpaid labor with systemic risk.</p><div><hr></div><h2>Conclusion</h2><p>The XZ backdoor wasn&#8217;t a failure of code. It was a failure of economics.</p><p>Jia Tan didn&#8217;t find a zero-day or exploit a race condition. He exploited the fact that trillion-dollar companies depend on unpaid volunteers, and then act surprised when those volunteers burn out and hand over the keys.</p><p>Linus&#8217;s Law &#8221;with enough eyeballs, all bugs are shallow&#8221; assumes the eyeballs are actually looking. But nobody reviews compression libraries. Nobody audits build scripts. Nobody funds the maintainer. Until something breaks.</p><p>The next time your CFO questions a $500,000 budget for open-source sponsorships, show them the XZ timeline. </p><p>Show them the 2.5 years of patient infiltration. Show them that one burnt-out maintainer was all that stood between production systems and a global, nation-state backdoor.</p><p>&#8220;Free&#8221; software isn&#8217;t free. You&#8217;re just deferring the payment. The only question is</p><p>Will you pay before the breach, or after?</p><p>Every dependency in your stack is either funded, or it&#8217;s a countdown timer.</p><div><hr></div><p>Credit to <strong><a href="https://www.youtube.com/@veritasium">Veritasium</a></strong> for their exceptional video breakdown of the Jia Tan timeline, which served as the foundation for this architectural teardown. <strong><a href="https://www.youtube.com/watch?v=aoag03mSuXQ">Watch it here</a></strong></p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.binarybox.org/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">Thanks for reading BinaryBox! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p>]]></content:encoded></item><item><title><![CDATA[Deep Dive - What it actually cost to Scale to 1 Million Requests per Second]]></title><description><![CDATA[1,000,000 Requests Per Second (RPS) on a single instance. The result? We hit it. But the bottleneck wasn&#8217;t the code logic. It wasn&#8217;t the database. It was the AWS billing department.]]></description><link>https://www.binarybox.org/p/deep-dive-what-it-actually-cost-to</link><guid isPermaLink="false">https://www.binarybox.org/p/deep-dive-what-it-actually-cost-to</guid><dc:creator><![CDATA[Ashok Vishwakarma]]></dc:creator><pubDate>Thu, 26 Feb 2026 06:01:22 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!YQ9Q!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56d79766-94bf-4543-bb32-d05de963ca79_720x360.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_!YQ9Q!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56d79766-94bf-4543-bb32-d05de963ca79_720x360.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YQ9Q!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56d79766-94bf-4543-bb32-d05de963ca79_720x360.jpeg 424w, https://substackcdn.com/image/fetch/$s_!YQ9Q!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56d79766-94bf-4543-bb32-d05de963ca79_720x360.jpeg 848w, https://substackcdn.com/image/fetch/$s_!YQ9Q!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56d79766-94bf-4543-bb32-d05de963ca79_720x360.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!YQ9Q!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56d79766-94bf-4543-bb32-d05de963ca79_720x360.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YQ9Q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56d79766-94bf-4543-bb32-d05de963ca79_720x360.jpeg" width="720" height="360" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/56d79766-94bf-4543-bb32-d05de963ca79_720x360.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:360,&quot;width&quot;:720,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Speedlines Images &#8211; Browse 3,500 Stock Photos, Vectors, and Video | Adobe  Stock&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Speedlines Images &#8211; Browse 3,500 Stock Photos, Vectors, and Video | Adobe  Stock" title="Speedlines Images &#8211; Browse 3,500 Stock Photos, Vectors, and Video | Adobe  Stock" srcset="https://substackcdn.com/image/fetch/$s_!YQ9Q!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56d79766-94bf-4543-bb32-d05de963ca79_720x360.jpeg 424w, https://substackcdn.com/image/fetch/$s_!YQ9Q!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56d79766-94bf-4543-bb32-d05de963ca79_720x360.jpeg 848w, https://substackcdn.com/image/fetch/$s_!YQ9Q!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56d79766-94bf-4543-bb32-d05de963ca79_720x360.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!YQ9Q!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56d79766-94bf-4543-bb32-d05de963ca79_720x360.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>Every CTO has a slide in their pitch deck that says: <em>&#8220;We will just auto-scale.&#8221;</em><br>It is the lie we tell investors to hide the fact that we haven&#8217;t thought about physics.</p><p>To test the limits of modern cloud infrastructure, I recently provisioned a monster. I spun up an <strong>AWS c8g.48xlarge</strong>, the &#8220;Beast.&#8221;</p><ul><li><p>192 vCPUs (ARM-based Graviton).</p></li><li><p>384 GB of DDR5 RAM.</p></li><li><p>50 Gbps baseline bandwidth.</p></li></ul><p>The goal? </p><p><strong>1,000,000 Requests Per Second (RPS)</strong> on a single instance.</p><p>The result? We hit it. </p><p>But the bottleneck wasn&#8217;t the code logic. It wasn&#8217;t the database. </p><p>It was the AWS billing department.</p><h2> The Compute Tax (Node.js vs. C++)</h2><p>We started with the industry standard, Node.js.</p><p>Node is famous for its non-blocking I/O. It&#8217;s supposed to be fast.</p><p>But when you throw 600,000 concurrent connections at it, the V8 engine starts to cough.</p><h3>The Node.js Ceiling (~500k RPS)</h3><p>Even with 192 cores, our Node cluster capped out at roughly 500,000 requests per second.</p><p>Why? <strong>Overhead.</strong></p><p>At this volume, the cost of creating a JavaScript object, managing the closure scope, and running the Garbage Collector becomes heavier than the actual request logic. The CPU wasn&#8217;t processing user data; it was managing V8 memory pointers.</p><h3>The C++ Fix (1M RPS)</h3><p>To unlock the hardware, we had to strip away the runtime. </p><p>We rewrote the service in <strong>C++ using the Drogon framework</strong>.</p><p>Drogon is brutal. It maps threads directly to cores. It has zero garbage collection overhead.</p><p>The result, <strong>1.2 Million RPS</strong> at 80% CPU utilization.</p><p>This forces a massive economic trade-off.</p><ul><li><p><strong>Option A (Node.js) - </strong>You pay for <strong>2x</strong> the hardware (two <code>c8g.48xlarge</code> servers) but you can hire JavaScript developers for $120k/year.</p></li><li><p><strong>Option B (C++) -</strong> You pay for <strong>1x</strong> hardware, but you need C++ systems engineers who cost $200k/year and take 6 months to hire.</p></li></ul><p>At small scale, hardware is cheap. </p><p>At massive scale, hardware is expensive. </p><p>Pick your poison.</p><h2>Disk vs. RAM</h2><p>Hitting the endpoint is easy. Saving the data is a suicide mission.</p><p>Try executing <code>INSERT INTO logs</code> 1,000,000 times per second on Postgres.</p><p>We tried writing to a Provisioned IOPS SSD (EBS io2 Block Express).</p><p>The disk latency spiked immediately. </p><p>The queue depth exploded. The SSD simply couldn't physically accept the write signals fast enough.</p><p>The database locked up.</p><p>To provision the 250,000+ IOPS required to even <em>attempt</em> this would cost roughly <strong>$30,000/month</strong> for a single volume.</p><p>The only way to absorb 1M RPS is to never touch the disk. We switched to a <strong>Redis Cluster</strong>.</p><p>RAM is orders of magnitude faster than NVMe. We could ingest the traffic easily.</p><p>The major trade-off was durability.</p><p>If the power fails on that rack in the data center, the last few seconds of data, potentially millions of transactions, are gone forever. </p><p>You are trading <strong>$25,000/</strong>month in EBS costs for the risk of data loss. </p><p>Is your data worth that much?</p><h2>Bandwidth</h2><p>We fixed the CPU. We fixed the Storage. </p><p>Then we got the bill for the network cable.</p><p>During a <strong>30-minute</strong> stress test, the &#8220;Beast&#8221; moved roughly <strong>60 Terabytes</strong> of data.</p><p><code>(1M RPS &#215; 30KB payload &#215; 1800 seconds &#8776; 54 TB).</code></p><h3>Public Traffic vs. Internal Traffic</h3><p>The cost depends entirely on <em>where</em> the data goes.</p><h4>Internal VPC (Inter-AZ, the test)</h4><p>60,000 GB &#215; $0.02 = <strong>$1,200</strong> for the 30-minute test.</p><h4>Public Internet (The Reality)</h4><p>If these were real users downloading data over the internet, you pay AWS standard egress rates which is ~$0.09 per GB</p><p>60,000 GB &#215; $0.09 = <strong>$5,400</strong>.</p><p><strong>That is $5,400 for a single 30-minute test.</strong></p><ul><li><p>60,000 GB &#215; $0.09 = <strong>$5,400</strong>.</p></li><li><p>That is <strong>$5,400 for a 30-minute test.</strong></p></li></ul><p>If you sustain 1M RPS for a month?</p><p>The cost will be <strong>~$7.9 Million/month</strong> (based on 730 hours).</p><p>This is a huge cost for the Bandwidth alone.</p><p>You can optimize your C++ code all you want. </p><p>You cannot optimize the size of a byte. If your business model involves high-throughput data transfer (video, logging, telemetry), the CPU cost is a rounding error. </p><p>The bandwidth will bankrupt you.</p><h2>The Price of 1 Million Req /Sec</h2><p>Let&#8217;s look at the actual receipt for this &#8220;experiment.&#8221;</p><h4><strong>The &#8220;Beast&#8221; Server (c8g.48xlarge)</strong></h4><ul><li><p><strong>$10.89 per hour.</strong> (Cheap!)</p></li></ul><h4><strong>The Load Generator Fleet</strong></h4><ul><li><p>It took <strong>60</strong> <code>c5.large</code> instances just to generate enough traffic to crash the Beast. </p></li><li><p><strong>$40.00 per hour.</strong></p></li></ul><h4><strong>The Failed Storage</strong></h4><ul><li><p>We provisioned a high-IOPS EBS volume for 2 hours before giving up. <strong>$200 (pro-rated).</strong></p></li></ul><h4><strong>The Bandwidth</strong></h4><ul><li><p><strong>Internal Scenario (Inter-AZ)</strong></p><ul><li><p>Even moving data between zones costs money. </p></li><li><p>$1,200 (30 mins) &#215; 2 = <strong>$2,400/hr.</strong></p></li></ul></li><li><p><strong>Public Scenario (Internet)</strong></p><ul><li><p>$5,400 (30 mins) &#215; 2 = <strong>$10,800/hr.</strong></p></li></ul></li></ul><h4><strong>Total Cost Summary (1 Hour)</strong></h4><ul><li><p><strong>Total Cost (Internal Test) - </strong>$11 + $40 + $200 + $2,400 = <strong>~$2,651.</strong></p></li><li><p><strong>Total Cost (Public Internet) -</strong> $11 + $40 + $200 + $10,800 = <strong>~$11,051.</strong></p><ul><li><p>This is estimated as we don&#8217;t have such money lying around to do the actual test.</p></li></ul></li></ul><p>To calculate a sustained month cost we can use the below formula</p><p><code>(Cost of Bandwidth + Cost of Compute) X 730 hours </code></p><h4><strong>Sustained Monthly Cost (Internet)</strong></h4><ul><li><p>AWS - ($10,800 bandwidth + $51 compute) &#215; 730 hours = <strong>~$7,921,000/month.</strong></p></li><li><p>GCP - (~$9,600 bandwidth + $51 compute) &#215; 730 hours = <strong>~$7,045,000/month.</strong> (Est. $0.08/GB egress)</p></li><li><p>Azure - (~$9,600 bandwidth + $51 compute) &#215; 730 hours = <strong>~$7,045,000/month.</strong> (Est. $0.08/GB egress)</p></li><li><p><strong>Bare Metal -</strong> <strong>~$140,000/month.</strong> (See breakdown below)</p></li></ul><h3>Bare Metal consideration</h3><p>To achieve this without the &#8220;Cloud Tax,&#8221; you move to wholesale IP Transit.</p><h4>Traffic Load</h4><p>120TB/hour converts to roughly <strong>266 Gbps</strong> sustained throughput.</p><h4>Bandwidth Cost</h4><p>~<strong>$0.50 per Mbps - </strong>Wholesale IP Transit (e.g., Cogent, Hurricane Electric) rough cost at this volume.</p><ul><li><p>266,000 Mbps &#215; $0.50 = <strong>$133,000/month</strong>.</p></li></ul><h4>Hardware (CapEx)</h4><ul><li><p>1x High-End Server (Dual AMD EPYC 96-core, 384GB RAM, 2x 100GbE NICs): <strong>~$25,000 (one-time)</strong>.</p></li><li><p><strong>~$700/month - </strong>Spread over 3 years.</p></li></ul><h4>Colocation Fee</h4><ul><li><p><strong>~$2,000/month</strong> - Rack space, power (2kW), and cross-connects.</p></li></ul><div><hr></div><h2>Conclusion</h2><p>1 Million Requests Per Second is a vanity metric.</p><p>Technically, it is solvable with C++, RAM, and big iron.</p><p>Economically, it is a different beast entirely.</p><p>If you are building a system, do not ask &#8220;Can we handle 1M RPS?&#8221;</p><p>Ask, &#8220;Is the user paying us enough to cover the $0.09/GB egress tax on 1M RPS?&#8221;</p><p>If the answer is no, stop optimizing your code and start optimizing your business model.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.binarybox.org/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">Thanks for reading BinaryBox! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><p></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Thought - How Atom built its own Assassin?]]></title><description><![CDATA[They built a runtime that allowed developers to create desktop applications using the web stack (HTML, CSS, JavaScript). They called it Atom Shell (Electron).]]></description><link>https://www.binarybox.org/p/thought-how-atom-built-its-own-assassin</link><guid isPermaLink="false">https://www.binarybox.org/p/thought-how-atom-built-its-own-assassin</guid><dc:creator><![CDATA[Ashok Vishwakarma]]></dc:creator><pubDate>Tue, 24 Feb 2026 06:01:16 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!5z7f!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb738b6ac-c2ba-406a-bcec-17fd201f4aa3_1200x675.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_!5z7f!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb738b6ac-c2ba-406a-bcec-17fd201f4aa3_1200x675.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5z7f!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb738b6ac-c2ba-406a-bcec-17fd201f4aa3_1200x675.jpeg 424w, https://substackcdn.com/image/fetch/$s_!5z7f!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb738b6ac-c2ba-406a-bcec-17fd201f4aa3_1200x675.jpeg 848w, https://substackcdn.com/image/fetch/$s_!5z7f!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb738b6ac-c2ba-406a-bcec-17fd201f4aa3_1200x675.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!5z7f!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb738b6ac-c2ba-406a-bcec-17fd201f4aa3_1200x675.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5z7f!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb738b6ac-c2ba-406a-bcec-17fd201f4aa3_1200x675.jpeg" width="1200" height="675" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b738b6ac-c2ba-406a-bcec-17fd201f4aa3_1200x675.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:675,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Atom Text Editor Will Officially Die Later This Year&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Atom Text Editor Will Officially Die Later This Year" title="Atom Text Editor Will Officially Die Later This Year" srcset="https://substackcdn.com/image/fetch/$s_!5z7f!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb738b6ac-c2ba-406a-bcec-17fd201f4aa3_1200x675.jpeg 424w, https://substackcdn.com/image/fetch/$s_!5z7f!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb738b6ac-c2ba-406a-bcec-17fd201f4aa3_1200x675.jpeg 848w, https://substackcdn.com/image/fetch/$s_!5z7f!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb738b6ac-c2ba-406a-bcec-17fd201f4aa3_1200x675.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!5z7f!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb738b6ac-c2ba-406a-bcec-17fd201f4aa3_1200x675.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>In the history of software engineering, there is no story more tragic than that of Atom.</p><p>In 2014, GitHub unveiled Atom to the world with a tagline that promised utopia, <em>&#8220;A hackable text editor for the 21st Century.&#8221;</em> </p><p>To realize this vision, the GitHub engineering team performed a miracle.</p><p>They built a runtime that allowed developers to create desktop applications using the web stack (HTML, CSS, JavaScript). They called it <strong>Atom Shell</strong>.</p><p>Today we know it as <strong><a href="https://www.electronjs.org/">Electron</a></strong>.</p><p>Atom didn&#8217;t just build an editor, they built the foundation for the next decade of software. </p><p>Slack, Discord, Figma, they all stand on the shoulders of Atom Shell. </p><p>But in a twist of cruel irony, a sleeping giant in Redmond picked up this exact tool, identified the one fatal flaw Atom refused to fix, and used it to build <strong><a href="https://code.visualstudio.com/">Visual Studio Code</a></strong>.</p><p>Atom provided the gun, the bullets, and the blueprint. </p><p>Microsoft simply pulled the trigger.</p><h2>The Single-Threaded Trap</h2><p>To understand why Atom died, we must look past the &#8220;bloat&#8221; complaints and analyze the Concurrency Model.</p><p>Atom&#8217;s core philosophy was <strong>Total Freedom</strong>.</p><p>They wanted the editor to be truly hackable. </p><p>This meant that a plugin developer could access <em>everything</em>. </p><p>They had direct access to the DOM. They shared the global scope. </p><p>Crucially, they ran on the <strong>Main Thread</strong>.</p><p>In a single-threaded environment like JavaScript, the Main Thread is holy ground. </p><p>It is responsible for event loops, layout calculations, and painting pixels.</p><p>By allowing plugins to inhabit this space, Atom created a zero-sum game for CPU cycles.</p><p>You install a &#8220;Bracket Matcher&#8221; plugin.</p><p>You type a bracket. The plugin wakes up to find the matching pair. It runs a synchronous search that takes 50ms.</p><p>For those 50ms, the UI renderer is blocked. The cursor stops blinking. The character you typed hangs in the buffer.</p><p>The &#8220;heaviness&#8221; users complained about was not memory usage, it was <strong>Thread Contention</strong>. </p><p>Atom relied on the &#8220;goodwill&#8221; of plugin authors to write non-blocking code. It was an architectural gamble that assumed developers would be disciplined.</p><p>They were not.</p><h2>VS Code&#8217;s Architecture (Extension Host)</h2><p>When Microsoft architected VS Code, led by <strong><a href="https://en.wikipedia.org/wiki/Erich_Gamma">Erich Gamma</a></strong> (one of the &#8220;Gang of Four&#8221;), they looked at Atom&#8217;s freedom and rejected it. </p><p>They prioritized <strong>Isolation</strong> over Hackability.</p><p>They introduced the <strong>Extension Host Process</strong>.</p><p>In VS Code, the editor UI runs in the Main Process and all the extensions run in a completely separate Node.js process.</p><p>There is a hard, impassable barrier between them.</p><ul><li><p>An extension <strong>cannot</strong> access the DOM.</p></li><li><p>An extension <strong>cannot</strong> access the window object.</p></li><li><p>An extension <strong>cannot</strong> freeze the renderer.</p></li></ul><p>If a VS Code extension enters an infinite loop or tries to mine crypto, the Extension Host might crash, but the user can still type. The cursor still blinks.</p><p>The &#8220;Hot Path&#8221; (the keystroke loop) is protected at all costs.</p><h2>RPC vs. Shared State</h2><p>This decision created a massive engineering trade-off.</p><h4>Atom&#8217;s Model (Shared State)</h4><p>Latency was near zero. A plugin can read the document buffer instantly from memory.</p><p>But it has volatile stability. One bad plugin kills the app.</p><h4>VS Code&#8217;s Model (RPC)</h4><p>Latency was high overhead. Since the plugin is in a different process, data must be serialized into JSON, sent over an IPC (Inter-Process Communication) pipe, deserialized, processed, reserialized, and sent back.</p><p>But it guaranteed stability. App will keep running even a bad plugin is installed.</p><h3>Why constraints won?</h3><p>VS Code bet that <strong>Input Latency</strong> was the only metric that mattered. </p><p>Users can tolerate a 100ms delay in syntax highlighting appearing. </p><p>But, they cannot tolerate a 10ms delay in a character appearing on screen.</p><p>By forcing communication through Asynchronous RPC, VS Code enforced &#8220;Mechanical Sympathy.&#8221; It acknowledged the reality of the JavaScript event loop and refused to fight it. </p><p>Atom tried to pretend the Main Thread was infinite.</p><h2>Constraints are Features</h2><p>The downfall of Atom teaches us a critical lesson in System Design</p><p><strong>Constraints are often more valuable than capabilities.</strong></p><p>Atom failed because it offered Total Freedom. </p><p>It gave developers a foot-gun, and developers proceeded to shoot the performance in the foot.</p><p>VS Code succeeded because it imposed Strict Constraints. </p><p>It built a sandbox that prevented developers from hurting the user experience, even if they wanted to.</p><div><hr></div><h2>Conclusion</h2><p>In 2022, GitHub (now owned by Microsoft) officially sunset Atom.</p><p>Atom did not die in vain. It was the martyr of the modern web desktop. </p><p>It proved the hypothesis that Electron could work. </p><p>It served as the glorious, messy prototype that paved the way for the production-grade architecture of VS Code.</p><p>Atom died so the ecosystem could live. And in the ruthless history of engineering, the prototype always gets deprecated.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.binarybox.org/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">Thanks for reading BinaryBox! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Database - How Over-Indexing cost us in Performance? ]]></title><description><![CDATA[We love Indexes, they are the first tool we reach for when a query is slow. But do you know every Index you add to speed up reads has a performance cost on every write.]]></description><link>https://www.binarybox.org/p/database-how-over-indexing-cost-us</link><guid isPermaLink="false">https://www.binarybox.org/p/database-how-over-indexing-cost-us</guid><dc:creator><![CDATA[Ashok Vishwakarma]]></dc:creator><pubDate>Thu, 19 Feb 2026 06:01:14 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!U7wy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6910aec-bdfb-4bfe-b2bc-e59fe5c3ecaf_736x387.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_!U7wy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6910aec-bdfb-4bfe-b2bc-e59fe5c3ecaf_736x387.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!U7wy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6910aec-bdfb-4bfe-b2bc-e59fe5c3ecaf_736x387.png 424w, https://substackcdn.com/image/fetch/$s_!U7wy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6910aec-bdfb-4bfe-b2bc-e59fe5c3ecaf_736x387.png 848w, https://substackcdn.com/image/fetch/$s_!U7wy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6910aec-bdfb-4bfe-b2bc-e59fe5c3ecaf_736x387.png 1272w, https://substackcdn.com/image/fetch/$s_!U7wy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6910aec-bdfb-4bfe-b2bc-e59fe5c3ecaf_736x387.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!U7wy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6910aec-bdfb-4bfe-b2bc-e59fe5c3ecaf_736x387.png" width="736" height="387" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e6910aec-bdfb-4bfe-b2bc-e59fe5c3ecaf_736x387.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:387,&quot;width&quot;:736,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;What Is a Database Index? Types, Best Practices &amp; AI Use Cases&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="What Is a Database Index? Types, Best Practices &amp; AI Use Cases" title="What Is a Database Index? Types, Best Practices &amp; AI Use Cases" srcset="https://substackcdn.com/image/fetch/$s_!U7wy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6910aec-bdfb-4bfe-b2bc-e59fe5c3ecaf_736x387.png 424w, https://substackcdn.com/image/fetch/$s_!U7wy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6910aec-bdfb-4bfe-b2bc-e59fe5c3ecaf_736x387.png 848w, https://substackcdn.com/image/fetch/$s_!U7wy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6910aec-bdfb-4bfe-b2bc-e59fe5c3ecaf_736x387.png 1272w, https://substackcdn.com/image/fetch/$s_!U7wy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6910aec-bdfb-4bfe-b2bc-e59fe5c3ecaf_736x387.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>We love indexes. They are the first tool we reach for when a query is slow. </p><p>A <code>SELECT</code> takes 4 seconds? </p><p>Add an index. Problem solved. Response time drops to 12 milliseconds. </p><p>You feel like a hero.</p><p>So you add another. And another. </p><p>A composite index for that dashboard query. </p><p>A partial index for that admin report. </p><p>A unique index on that email column. </p><p>Before you know it, your table has 12 indexes and your insert latency has quietly tripled.</p><p>Nobody notices. Not yet.</p><p>This article is about the other side of the indexing story, the side that almost nobody talks about. </p><p>Not "how to create the right index" but "how your indexes are silently destroying your write performance."</p><h2>What happens when you INSERT a row?</h2><p>To understand why over-indexing is dangerous, you need to understand what the database actually does when you insert a single row.</p><p>On a table with <strong>zero indexes</strong> (a heap table), an <strong>INSERT</strong> is almost trivially cheap. The database finds a page with free space, writes the row, and it is done. This is mostly a sequential memory operation. <strong>It is fast.</strong></p><p>Now add a Primary Key. </p><p>That key is backed by a B-Tree index. The database must now also navigate that B-Tree, find the correct leaf page, and insert the key. If the leaf page is full, the database performs a <strong>page split</strong>, it allocates a new page, redistributes half the entries, and updates the parent node pointers. </p><p>This is the same mechanics I described in my <strong><a href="https://www.binarybox.org/p/database-the-cost-of-using-uuid-as">UUID v4 article</a></strong>.</p><p>Now add a second index. And a third. </p><p>For <strong>every single INSERT</strong>, the database must repeat this B-Tree navigation and insertion process <strong>once per index</strong>. Five indexes means five separate B-Tree insertions for every row you write.</p><p>The critical insight is this, the database cannot skip any of them. Even if an index exists only to serve a query that runs once a month, it must be updated on every single write.</p><h2>The Multiplier Effect</h2><p><strong><a href="https://winand.at/">Markus Winand</a></strong>, author of <em><strong><a href="https://github.com/quynhethereal/books-2/blob/master/databases/SQL%20Performance%20Explained.pdf">SQL Performance Explained</a></strong></em> and the site <strong><a href="https://use-the-index-luke.com/">use-the-index-luke.com</a></strong>, published a benchmark that should be pinned to every engineer's wall</p><p><em>&#8220;<strong>A table with zero indexes can be 100x faster to insert into than a table with a single index.</strong> And each additional index degrades insert performance further in a roughly linear fashion.&#8221;</em></p><p>Think about that. </p><p>You go from zero indexes to one, and your insert speed drops by two orders of magnitude. The actual data write is trivial. The <strong>index maintenance is the expensive part.</strong></p><p>Now consider what happens in production. You have a table with 8 indexes. You deploy 10 application instances. </p><p>Each instance is doing 500 writes per second to that table. Every write triggers 8 separate B-Tree insertions. </p><p>That is 40,000 index operations per second hitting your database. </p><p>And when you wonder why your RDS CPU is at 85%, nobody thinks to look at the index count.</p><h2>It costs beyond Write Latency</h2><p>The write speed penalty is only the beginning. Over-indexing creates a cascade of secondary problems that are even harder to diagnose.</p><h3><strong><a href="https://en.wikipedia.org/wiki/Write-ahead_logging">WAL</a> Amplification.</strong> </h3><p>In PostgreSQL, every change to an index page generates Write-Ahead Log (WAL) entries. More indexes means more WAL data. </p><p>That WAL is shipped to your replicas. It is archived for point-in-time recovery. It is processed by your backup systems. </p><p>Unnecessary indexes do not just slow down your primary, they increase replication lag, inflate your backup storage, and slow down disaster recovery.</p><h3>Buffer Pool Pressure</h3><p>Every index occupies pages in the shared buffer pool (PostgreSQL) or InnoDB buffer pool (MySQL). </p><p>Indexes you never query still compete for memory with the indexes you actually need. </p><p>When your buffer pool is full of cold, unused index pages, the hot pages that serve your real queries get evicted. </p><p>This causes more disk I/O for the queries you are trying to make fast. </p><p>The irony, an unused index can make your <em>other</em> indexes slower.</p><h3>Vacuum and Maintenance Overhead</h3><p>In PostgreSQL, <code>VACUUM</code> must process every index on a table to clean up dead tuples. </p><p>A table with 2 indexes vacuums twice as fast as a table with 8. </p><p>If <code>autovacuum</code> falls behind because it is spending all its time maintaining unnecessary indexes, you get <strong>table bloat</strong>, dead rows pile up, the table grows on disk, and sequential scans (which ignore indexes entirely) get slower and slower.</p><h3>Query Planner Confusion</h3><p>Every index gives the query planner another option to consider. </p><p>With many indexes, the planner spends more time evaluating plans, and the chance of it choosing a suboptimal plan increases. </p><p>PostgreSQL's planner has been measured to slow down measurably when a table has a large number of indexes, especially without prepared statements.</p><h2>How Over-Indexing happens</h2><p>We are not doing it intentionally for sure. </p><p>Nobody sets out to over-index a table. It happens gradually, through a series of individually reasonable decisions.</p><h3>The "Just Add an Index" Reflex</h3><p>A query is slow. </p><p>Someone runs <code>EXPLAIN ANALYZE</code>, sees a sequential scan, and creates an index. </p><p>The query gets faster. </p><p>Nobody checks if an existing index already covers the query, or if the query itself could be restructured.</p><h3>Composite Index Duplication</h3><p>You have an index on <code>(user_id, created_at)</code>. </p><p>Someone creates a new index on <code>(user_id)</code> because their query only filters by <code>user_id</code>. </p><p>But a composite index on <code>(user_id, created_at)</code> already supports lookups by <code>user_id</code> alone, it is a "leftmost prefix" index. </p><p>The new index is pure waste.</p><h3>Abandoned Feature Indexes</h3><p>A feature was built six months ago. </p><p>It had specific queries that needed indexes. The feature was removed or rewritten. </p><p>The indexes stayed. Nobody went back to clean them up. </p><p>The codebase forgot. The database remembers.</p><h3>ORM-Generated Indexes</h3><p>ORMs like Sequlize, Django, Rails, and Hibernate often generate indexes automatically on every foreign key, on every column used in a <code>unique_together</code>, sometimes on columns that are barely queried.</p><p>Engineers trust the ORM defaults without auditing them.</p><p>Let me tell you a story.</p><h2>The story (it&#8217;s not a fiction though)</h2><p>I once worked with a SaaS company that had an <code>events</code> table tracking user activity. </p><p>The table received about 3,000 inserts per second during peak hours. </p><p>Over two years, different teams had added indexes for various reporting queries, admin dashboards, and one-off data exports.</p><p>The table had <strong>14 indexes</strong>.</p><p>The symptom, insert latency would spike to 800ms during peak traffic, triggering timeouts in the application layer. </p><p>They had already upgraded the RDS instance twice. They were looking at sharding.</p><p>I ran a simple query against <code>pg_stat_user_indexes</code></p><pre><code>SELECT
    schemaname || '.' || relname AS table,
    indexrelname AS index,
    idx_scan AS times_used,
    pg_size_pretty(pg_relation_size(indexrelid)) AS size
FROM pg_stat_user_indexes
WHERE relname = 'events'
ORDER BY idx_scan ASC;</code></pre><p>Six of the fourteen indexes had <strong>zero scans</strong> since the last statistics reset (which was three months prior). </p><p>Two more had fewer than 10 scans total, they were backing queries that had been removed from the codebase months ago.</p><p>The total size of those 8 unused indexes was <strong>11 GB</strong>. </p><p>Sitting in memory. Being updated 3,000 times per second. </p><p>Generating WAL. Slowing down vacuum. </p><p>Contributing nothing.</p><p>We dropped them. Insert latency fell from 800ms peaks to under 50ms. </p><p>CPU dropped from 80% to 35%. They cancelled the sharding project.</p><p>The fix was not adding something. It was removing something.</p><h2>How to Find and Kill Unused Indexes</h2><p>Here is a practical process for auditing your indexes in PostgreSQL.</p><h3>Step 1 - Check When Stats Were Last Reset</h3><p>Before trusting scan counts, verify that your statistics have been accumulating long enough to be meaningful.</p><pre><code>SELECT
    stats_reset,
    age(now(), stats_reset) AS stats_age
FROM pg_stat_database
WHERE datname = current_database();</code></pre><p>If the stats were reset yesterday, the scan counts are not reliable. Wait at least one full business cycle (ideally a month) before making decisions.</p><h3>Step 2 - List All Indexes by Usage</h3><pre><code>SELECT
    schemaname || '.' || relname AS table,
    indexrelname AS index,
    idx_scan AS scans,
    pg_size_pretty(pg_relation_size(indexrelid)) AS size,
    pg_size_pretty(pg_total_relation_size(relid)) AS table_total_size
FROM pg_stat_user_indexes
ORDER BY idx_scan ASC;</code></pre><p>Anything with <code>idx_scan = 0</code> over a multi-week window is a candidate for removal. </p><p>Anything with very low scan counts (single digits) should be investigated.</p><h3>Step 3 - Check for Duplicate and Overlapping Indexes</h3><p>A composite index on <code>(a, b)</code> makes a standalone index on <code>(a)</code> redundant for most queries. Look for these overlaps.</p><pre><code>SELECT
    pg_size_pretty(sum(pg_relation_size(idx))::bigint) AS total_size,
    (array_agg(idx))[1] AS index_1,
    (array_agg(idx))[2] AS index_2
FROM (
    SELECT
        indexrelid::regclass AS idx,
        (indrelid::regclass)::text AS table_name,
        (indkey::text) AS columns
    FROM pg_index
) sub
GROUP BY table_name, columns
HAVING count(*) &gt; 1;</code></pre><h3>Step 4 - Drop with a Safety Net</h3><p>Do not drop indexes directly in production. First, make them invisible to the planner (PostgreSQL 17+)</p><pre><code>-- PostgreSQL 17+ only
ALTER INDEX idx_events_legacy SET (deduplicate_items = off);
-- Or simply: monitor after dropping</code></pre><p>For older PostgreSQL versions, the safest approach is, drop the index, monitor for one to two weeks, and keep the <code>CREATE INDEX</code> statement saved so you can recreate it if a query regresses.</p><pre><code>-- Save the DDL first
SELECT pg_get_indexdef(indexrelid)
FROM pg_index
WHERE indexrelid = 'idx_events_legacy'::regclass;

-- Then drop
DROP INDEX CONCURRENTLY idx_events_legacy;</code></pre><p>Always use <code>DROP INDEX CONCURRENTLY</code> to avoid locking the table.</p><h2>The Rule of Thumb</h2><p>There is no magic number for how many indexes a table should have. But there is a principle</p><p><strong>Every index must justify its existence against the write cost it imposes.</strong></p><p>If you cannot point to a specific, frequently-executed query that needs an index, that index should not exist. </p><p>"We might need it someday" is not a justification. </p><p>Creating an index takes seconds. The cost of maintaining a useless one runs 24 hours a day, 365 days a year.</p><p>For write-heavy tables (logging, events, analytics, time-series), aim for the absolute minimum, a primary key and perhaps one or two carefully chosen indexes. </p><p>For read-heavy tables with infrequent writes (reference data, configuration, product catalogs), you can afford more indexes.</p><p>The question is never "Will this index make my reads faster?" The answer is almost always yes. </p><p>The real question is <strong>"Is the read improvement worth the write cost across every insert, update, and delete this table will ever process?"</strong></p><div><hr></div><h2>Conclusion</h2><p>Indexes are not free. </p><p>Every index you create is a standing instruction to the database, "Every time any row in this table changes, do extra work." </p><p>Most engineers treat indexes as read-side optimizations and forget they are write-side penalties.</p><p>The next time you reach for <code>CREATE INDEX</code>, stop and ask three questions</p><ol><li><p><strong>Is there already an index that covers this query?</strong> Check for leftmost-prefix matches on existing composite indexes.</p></li><li><p><strong>How often does this query actually run?</strong> If it runs once a day, you probably do not need an index. If it runs 10,000 times a second, you probably do.</p></li><li><p><strong>How write-heavy is this table?</strong> A table receiving thousands of inserts per second pays a much higher tax per index than a table that changes once an hour.</p></li></ol><p>And once a quarter, run the audit queries above. </p><p>Find your dead indexes. </p><p>Drop them. </p><p>Your database will thank you with lower CPU, faster writes, less replication lag, and a smaller storage bill.</p><p>Stop hoarding indexes. Start earning them.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.binarybox.org/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">Thanks for reading BinaryBox! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Deep Dive - Why Linux Process creation is weird?]]></title><description><![CDATA[In the Unix world, creating a new process is not an act of construction, it is an act of biological division followed by a brain transplant.]]></description><link>https://www.binarybox.org/p/deep-dive-why-linux-process-creation</link><guid isPermaLink="false">https://www.binarybox.org/p/deep-dive-why-linux-process-creation</guid><dc:creator><![CDATA[Ashok Vishwakarma]]></dc:creator><pubDate>Tue, 17 Feb 2026 06:01:06 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!nNFv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F362471d8-6a01-437d-a454-300e7d5b8a0a_1200x628.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_!nNFv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F362471d8-6a01-437d-a454-300e7d5b8a0a_1200x628.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nNFv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F362471d8-6a01-437d-a454-300e7d5b8a0a_1200x628.jpeg 424w, https://substackcdn.com/image/fetch/$s_!nNFv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F362471d8-6a01-437d-a454-300e7d5b8a0a_1200x628.jpeg 848w, https://substackcdn.com/image/fetch/$s_!nNFv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F362471d8-6a01-437d-a454-300e7d5b8a0a_1200x628.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!nNFv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F362471d8-6a01-437d-a454-300e7d5b8a0a_1200x628.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nNFv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F362471d8-6a01-437d-a454-300e7d5b8a0a_1200x628.jpeg" width="1200" height="628" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/362471d8-6a01-437d-a454-300e7d5b8a0a_1200x628.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:628,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Linux operating system &#8211; LovHind&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Linux operating system &#8211; LovHind" title="Linux operating system &#8211; LovHind" srcset="https://substackcdn.com/image/fetch/$s_!nNFv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F362471d8-6a01-437d-a454-300e7d5b8a0a_1200x628.jpeg 424w, https://substackcdn.com/image/fetch/$s_!nNFv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F362471d8-6a01-437d-a454-300e7d5b8a0a_1200x628.jpeg 848w, https://substackcdn.com/image/fetch/$s_!nNFv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F362471d8-6a01-437d-a454-300e7d5b8a0a_1200x628.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!nNFv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F362471d8-6a01-437d-a454-300e7d5b8a0a_1200x628.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>To a user like us, launching an application is a singular atomic event. </p><p>We double-click the App icon, and App appears. Simple.</p><p>To a Windows kernel engineer, this makes perfect sense. </p><p>You call <code>CreateProcess()</code>. You pass it the path to the executable, some flags, and the OS allocates memory, loads the <code>.exe</code> file from the disk, and sets the instruction pointer to the entry point. </p><p>It creates a brand new thing from scratch. It is sane. It is logical.</p><p>To a Linux kernel engineer, this is boring.</p><p>In the Unix world, creating a new process is not an act of construction, it is an act of biological division followed by a brain transplant. </p><p>We don&#8217;t just &#8220;start&#8221; a program. We clone the current program, and then we lobotomize the clone.</p><p>Enter the <code>fork()</code> and <code>execve()</code> dance.</p><h2><code>fork()</code></h2><p>In Linux, there is (almost) only one way to create a new process, you have to duplicate an existing one.</p><p>When your shell (bash/zsh) wants to run <code>ls</code>, it calls the system call <code>fork()</code>.<br>This function takes <strong>zero arguments</strong>.</p><pre><code><code>pid_t pid = fork();</code></code></pre><p>When the CPU executes this instruction, the kernel performs <strong>Mitosis</strong>. It creates an exact duplicate of the current process.</p><ul><li><p><strong>Memory</strong> - It copies the Stack, the Heap, and the Global variables (Logically, via Copy-on-Write).</p></li><li><p><strong>File Descriptors - </strong>It copies the table of open files.</p></li><li><p><strong>CPU State -</strong> It copies the registers and, crucially, the <strong>Instruction Pointer</strong>.</p></li></ul><h3>The &#8220;Multiverse&#8221; Moment</h3><p>This is the part that breaks the brain of every Computer Science 101 student.</p><p>When <code>fork()</code> returns, it returns <strong>twice</strong>. </p><ul><li><p>It returns once in the original process (the Parent). </p></li><li><p>It returns simultaneously in the new process (the Child).</p></li></ul><p>Both processes are now at the exact same line of code. They are identical.</p><p>The only way the code knows &#8220;Who am I?&#8221; is by checking the return value.</p><pre><code><code>if (pid == 0) {
    // I am the Child (The Clone)
} else {
    // I am the Parent (The Shell)
    // 'pid' holds the ID of my new child
}</code></code></pre><h2><code>execve()</code></h2><p>At this exact moment, we have two copies of the Shell running. We don&#8217;t want two shells, we want our App.</p><p>This is where the child process performs the sacrifice. It calls <code>execve()</code> (or one of its wrappers like <code>execvp</code>).</p><pre><code><code>// Inside the Child process
execve("/usr/bin/app", args, env);</code></code></pre><p>This syscall is destructive.</p><ol><li><p><strong>Wipe -</strong> The kernel discards the entire memory address space of the process. The stack, heap, and old code are annihilated.</p></li><li><p><strong>Load -</strong> The kernel maps the new executable (<code>app</code>) into memory.</p></li><li><p><strong>Reset -</strong> The Instruction Pointer is reset to the entry point of the new binary.</p></li></ol><p>The Process ID (PID) remains the same. </p><p>The file descriptors (mostly) remain open. But the &#8220;soul&#8221; of the process has been swapped out. </p><p>The code that called <code>execve</code> creates its own executioner, it never executes the line after <code>execve</code> because it no longer exists.</p><h2>Windows vs. Linux</h2><p>Why does Linux do this weird two-step dance instead of the Windows one-shot approach?</p><h3>The Monolith (<code>CreateProcess</code>)</h3><p>Windows treats process creation as a massive configuration task. </p><p>The <code>CreateProcess</code> API takes <strong>10 parameters</strong>. </p><p>If you want to customize how the new process starts (e.g., redirecting Standard Output to a file), you have to fill out complex <code>STARTUPINFO</code> structures and pass them in.</p><p>It is efficient for the OS, but it creates a rigid API surface.</p><h3>The Primitives (<code>fork</code> + <code>exec</code>)</h3><p>By splitting creation (<code>fork</code>) from execution (<code>exec</code>), Unix gave us a magical &#8220;Interim State.&#8221;</p><p>Between the <code>fork()</code> and the <code>exec()</code>, the Child process is running, but it&#8217;s still running the <em>shell&#8217;s</em> code. </p><p>This allows the child to configure itself before it turns into the new program.</p><p><strong>This is how Redirection works.</strong></p><p>When you run <code>ls &gt; output.txt</code>, the shell</p><ol><li><p>Forks.</p></li><li><p><strong>Inside the child (before exec):</strong> It closes <code>stdout</code> and opens <code>output.txt</code> in its place.</p></li><li><p>Execs <code>ls</code>.</p></li></ol><p>The <code>ls</code> program doesn&#8217;t know about <code>output.txt</code>. It just writes to file descriptor 1. It works because the &#8220;Clone&#8221; adjusted its own plumbing before the brain transplant.</p><h3>The &#8220;Tree&#8221; Consequence</h3><p>Because every process must be spawned by an existing process, Linux has a strict <strong>Process Tree</strong>.</p><ul><li><p>Process A spawns B.</p></li><li><p>B spawns C.</p></li><li><p>Trace it all the way back, and you find <strong>PID 1</strong> (<code>systemd</code> or <code>init</code>).</p></li></ul><p>If you want to view the Process tree use <code>pstree -c</code> in your linux terminal.</p><p>In Windows, processes act more like independent objects. In Linux, they are a family line, traceable to a single ancestor.</p><h2>Why we engineers should care?</h2><p>You might be thinking, &#8220;I write Python/Node/Go. Why do I care about syscalls?&#8221; </p><p>Because this mechanism explains bugs that high-level abstractions cannot.</p><h3>The Redis Latency Spike</h3><p>Redis uses <code>fork()</code> to create background snapshots (RDB). </p><p>It relies on &#8220;Copy-on-Write&#8221; (CoW) so it doesn&#8217;t actually double RAM usage instantly.</p><p>However, <code>fork()</code> must copy the <strong>Page Tables</strong>. </p><p>If your Redis instance uses 60GB of RAM, the kernel pauses the main thread just to clone the page table mapping. </p><p>This causes the infamous &#8220;latency spike&#8221; in large Redis instances. It&#8217;s not the data copying; it&#8217;s the <code>fork</code> overhead itself.</p><h3>The Thread Safety Trap</h3><p>If your application is multi-threaded and you call <code>fork()</code>, the kernel <strong>only copies the thread that called fork</strong>. </p><p>The other threads vanish in the child.</p><p><strong>The Horror, </strong>if a vanished thread was holding a mutex (lock) when <code>fork()</code> happened, that mutex is now locked forever in the child process, owned by a ghost thread that doesn&#8217;t exist. </p><p>If the child tries to acquire that lock (e.g., calling <code>malloc</code>), it will deadlock instantly.</p><h3>The Zombie Leak</h3><p>If you spawn a child process but never read its exit code (via <code>waitpid</code>), the kernel keeps the process entry alive in the process table so you can read the status later. </p><p>If you forget to do this, your server fills up with &#8220;Zombie&#8221; processes (<code>defunct</code>), eventually hitting the system-wide process limit and crashing.</p><div><hr></div><h2>Conclusion</h2><p>High-level languages try to hide this from you. </p><p>Python&#8217;s <code>subprocess.run</code> or Node&#8217;s <code>child_process.spawn</code> are just wrappers. </p><p>Even modern POSIX introduced <code>posix_spawn</code> to mimic the Windows style for performance reasons (avoiding the overhead of copying page tables for a fork that immediately execs).</p><p>But underneath your abstractions, the machine is still doing the dance.</p><ul><li><p><strong>Windows</strong> treats processes as <strong>Objects</strong> to be instantiated.</p></li><li><p><strong>Linux</strong> treats processes as <strong>Life</strong> to be evolved.</p></li></ul><p>Next time you see a &#8220;Zombie Process&#8221; in <code>top</code>, remember, it&#8217;s not a bug. It&#8217;s a child waiting for its parent to acknowledge its death. </p><p>That&#8217;s just nature.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.binarybox.org/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">Thanks for reading BinaryBox! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Stop Looking for Bugs in Code Reviews]]></title><description><![CDATA[Add the cost of the context switch, which research shows takes ~23 minutes to recover from, and that comment about a variable name just cost the company $100 to $500 in lost productivity.]]></description><link>https://www.binarybox.org/p/stop-looking-for-bugs-in-code-reviews</link><guid isPermaLink="false">https://www.binarybox.org/p/stop-looking-for-bugs-in-code-reviews</guid><dc:creator><![CDATA[Ashok Vishwakarma]]></dc:creator><pubDate>Thu, 12 Feb 2026 06:00:50 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!JyZT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1c355fb-05f2-4502-bee8-78ad0bff6376_1000x562.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_!JyZT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1c355fb-05f2-4502-bee8-78ad0bff6376_1000x562.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!JyZT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1c355fb-05f2-4502-bee8-78ad0bff6376_1000x562.jpeg 424w, https://substackcdn.com/image/fetch/$s_!JyZT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1c355fb-05f2-4502-bee8-78ad0bff6376_1000x562.jpeg 848w, https://substackcdn.com/image/fetch/$s_!JyZT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1c355fb-05f2-4502-bee8-78ad0bff6376_1000x562.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!JyZT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1c355fb-05f2-4502-bee8-78ad0bff6376_1000x562.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!JyZT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1c355fb-05f2-4502-bee8-78ad0bff6376_1000x562.jpeg" width="1000" height="562" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f1c355fb-05f2-4502-bee8-78ad0bff6376_1000x562.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:562,&quot;width&quot;:1000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;How we improved the process of Code and Functional Reviews&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="How we improved the process of Code and Functional Reviews" title="How we improved the process of Code and Functional Reviews" srcset="https://substackcdn.com/image/fetch/$s_!JyZT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1c355fb-05f2-4502-bee8-78ad0bff6376_1000x562.jpeg 424w, https://substackcdn.com/image/fetch/$s_!JyZT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1c355fb-05f2-4502-bee8-78ad0bff6376_1000x562.jpeg 848w, https://substackcdn.com/image/fetch/$s_!JyZT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1c355fb-05f2-4502-bee8-78ad0bff6376_1000x562.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!JyZT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1c355fb-05f2-4502-bee8-78ad0bff6376_1000x562.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>Last week, we talked about &#8220;Career Survival.&#8221; Survival isn&#8217;t just about writing code; it&#8217;s about <strong>leverage</strong>. </p><p>And right now, your leverage is bleeding out in the comments section of a Pull Request.</p><p>Here is a scenario I see in high-growth startups every day</p><ol><li><p>A Senior Engineer opens a PR.</p></li><li><p>Another Senior Engineer stops their deep work, pays the cognitive tax of a context switch, and opens the diff.</p></li><li><p>They spend 15 minutes debating <code>camelCase</code> vs <code>snake_case</code> or pointing out a missing semicolon.</p></li></ol><p>Let&#8217;s do the math.</p><p>A Principal Engineer&#8217;s fully loaded cost (salary, equity, benefits, overhead) is easily $200+ per hour. </p><p>Add the cost of the context switch, which research shows takes ~23 minutes to recover from, and that comment about a variable name just cost the company $100 to $500 in lost productivity.</p><p>If you are a human being and you are commenting on syntax, you are wasting the company&#8217;s money. </p><p>You are doing a job that a script does better, faster, and for free.</p><h2>The Lint Barrier</h2><p>I have a strict rule for my teams</p><p><strong>If a machine can catch it, a human shouldn&#8217;t see it.</strong></p><p>A Pull Request should never reach a human reviewer unless it has already passed a gauntlet of cold, unfeeling robots. </p><p>This is the <strong>Lint Barrier</strong>.</p><ul><li><p><strong>ESLint/Pylint -</strong> Catches syntax errors and unused variables.</p></li><li><p><strong>Prettier/Black -</strong> Enforces formatting.</p></li><li><p><strong>Static Analysis -</strong> Catches potential type errors.</p></li></ul><p>If a PR fails any of these, I don&#8217;t want a notification. I don&#8217;t want to see it.</p><h3>The &#8220;Nitpick&#8221; Ban</h3><p>&#8220;Nits&#8221; (minor, non-blocking suggestions) are poison. </p><p>They clutter the feedback loop. They make the author feel defensive. </p><p>Worst of all, they distract the reviewer from the structural flaws hiding in the logic.</p><p>When you flood a PR with 20 comments about indentation, you feel productive. </p><p>You aren&#8217;t. You&#8217;re just being a spellchecker.</p><h2>The Hierarchy of Review</h2><p>So, if you can&#8217;t complain about whitespace, what are you supposed to do? </p><p>You do the job we actually pay you for. You look for the things a computer cannot understand.</p><p>Your review should follow this hierarchy</p><h3>1. Architecture and Design</h3><ul><li><p>Does this fit our existing design patterns, or is it a bespoke snowflake?</p></li><li><p>Is this over-engineered? (The &#8220;YAGNI&#8221; check).</p></li><li><p>Does this introduce a circular dependency?</p></li></ul><h3>2. Data Integrity</h3><ul><li><p><strong>The Database Lock -</strong> Will this migration lock the <code>users</code> table for 10 minutes during peak traffic?</p></li><li><p><strong>Race Conditions -</strong> What happens if two requests hit this endpoint simultaneously?</p></li><li><p><strong>State Management -</strong> Are we mutating state that should be immutable?</p></li></ul><h3>3. Security</h3><ul><li><p>Is there an IDOR (Insecure Direct Object Reference) vulnerability here?</p></li><li><p>Are we sanitizing inputs?</p></li><li><p>Are we logging PII (Personally Identifiable Information)?</p></li></ul><h3>4. Maintainability</h3><ul><li><p>Will the next person understand this in 6 months?</p></li><li><p>Is the business logic exposed, or is it buried in 5 layers of abstraction?</p></li></ul><h2>&#8220;LGTM&#8221; is not Lazy</h2><p>There is a stigma that a fast &#8220;LGTM&#8221; (Looks Good To Me) implies laziness.</p><p>In a mature engineering organization, <strong>LGTM is a badge of honor.</strong></p><p>It means the automated pipeline did the heavy lifting. It means the tests passed, the linter is happy, the style is compliant, and the architecture is sound. </p><p>It means the reviewer trusts the system.</p><h3>The Bikeshedding Trap</h3><p><strong><a href="https://en.wikipedia.org/wiki/C._Northcote_Parkinson">Cyril Northcote Parkinson</a></strong> coined the &#8220;<strong><a href="https://en.wikipedia.org/wiki/Law_of_triviality">Law of Triviality</a></strong>&#8221; (Bikeshedding). </p><p>He observed that a committee would approve a $10 million nuclear power plant in 10 minutes but spend 45 minutes debating the color of the bike shed.</p><p>Why? </p><p><strong>Because nuclear physics is hard, but everyone has an opinion on paint.</strong></p><p>Engineering teams are the same. </p><p>We argue about tabs vs. spaces because understanding a distributed race condition is hard. </p><p>Syntax is easy. Do not fall into the trap of low-leverage debates.</p><h2>Here what you should do</h2><p>You want to stop wasting $500 on variable name discussions? </p><p>Implement this today</p><h4><strong>Agree Once, Then Never Again</strong></h4><ul><li><p>Sit the team down. </p></li><li><p>Argue about the Linter Config for one hour. </p></li><li><p>Pick a standard (Airbnb, Google, whatever). </p></li><li><p>Commit that config file. </p></li></ul><p><strong>The discussion is now closed forever.</strong></p><h4><strong>The Husky Hook</strong></h4><p>Add a pre-commit hook (using tools like Husky) that prevents a developer from even committing code that violates the style guide.</p><h4><strong>The &#8220;Style&#8221; Ban</strong></h4><p>Make it a team policy. </p><p>If a reviewer comments on code style in a PR, <em>the reviewer</em> is in the wrong, not the coder. </p><p>Update the linter instead.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.binarybox.org/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">Thanks for reading BinaryBox! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p>]]></content:encoded></item><item><title><![CDATA[JavaScript - The Garbage Collector is Your Roommate (and you are a bad tenant)]]></title><description><![CDATA[You are not the landlord of this memory. You are just a tenant. And the cleaning service, V8&#8217;s Garbage Collector (GC), doesn&#8217;t come on your command. It comes when it feels like it.]]></description><link>https://www.binarybox.org/p/javascript-the-garbage-collector</link><guid isPermaLink="false">https://www.binarybox.org/p/javascript-the-garbage-collector</guid><dc:creator><![CDATA[Ashok Vishwakarma]]></dc:creator><pubDate>Tue, 10 Feb 2026 06:00:50 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Mem4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb25d49d0-445d-4499-bcce-a57c9bfa5f2c_1184x623.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_!Mem4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb25d49d0-445d-4499-bcce-a57c9bfa5f2c_1184x623.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Mem4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb25d49d0-445d-4499-bcce-a57c9bfa5f2c_1184x623.png 424w, https://substackcdn.com/image/fetch/$s_!Mem4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb25d49d0-445d-4499-bcce-a57c9bfa5f2c_1184x623.png 848w, https://substackcdn.com/image/fetch/$s_!Mem4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb25d49d0-445d-4499-bcce-a57c9bfa5f2c_1184x623.png 1272w, https://substackcdn.com/image/fetch/$s_!Mem4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb25d49d0-445d-4499-bcce-a57c9bfa5f2c_1184x623.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Mem4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb25d49d0-445d-4499-bcce-a57c9bfa5f2c_1184x623.png" width="728" height="383.06081081081084" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b25d49d0-445d-4499-bcce-a57c9bfa5f2c_1184x623.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:623,&quot;width&quot;:1184,&quot;resizeWidth&quot;:728,&quot;bytes&quot;:41635,&quot;alt&quot;:&quot;The 10 Most Common JavaScript Issues Developers Face | Toptal&#174;&quot;,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The 10 Most Common JavaScript Issues Developers Face | Toptal&#174;" title="The 10 Most Common JavaScript Issues Developers Face | Toptal&#174;" srcset="https://substackcdn.com/image/fetch/$s_!Mem4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb25d49d0-445d-4499-bcce-a57c9bfa5f2c_1184x623.png 424w, https://substackcdn.com/image/fetch/$s_!Mem4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb25d49d0-445d-4499-bcce-a57c9bfa5f2c_1184x623.png 848w, https://substackcdn.com/image/fetch/$s_!Mem4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb25d49d0-445d-4499-bcce-a57c9bfa5f2c_1184x623.png 1272w, https://substackcdn.com/image/fetch/$s_!Mem4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb25d49d0-445d-4499-bcce-a57c9bfa5f2c_1184x623.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>Let&#8217;s start with a line of code I see in Pull Requests from developers who think they are &#8220;optimizing&#8221; memory usage.</p><pre><code><code>const user = { 
    id: 1, 
    hugeData: new Array(1000000).fill('garbage') 
};

// "I'm freeing up RAM, boss!"
delete user.hugeData;</code></code></pre><p>You think you just freed 8MB of RAM. You think the memory was released the moment that semicolon hit.</p><p>But, in reality, you didn&#8217;t free memory. </p><p>You just deleted a key from a hash map (and destroyed the Hidden Class optimization in the process, but that&#8217;s a rant for another day). </p><p>The massive array still exists in the Heap. It sits there, occupying space, waiting.</p><p>You are not the landlord of this memory. You are just a tenant. And the cleaning service, V8&#8217;s Garbage Collector (GC), doesn&#8217;t come on your command. It comes when it feels like it.</p><h2>Mark and Sweep</h2><p>Think of your application&#8217;s memory (the Heap) as a messy apartment. </p><p>You are the hoarders. </p><p>The Garbage Collector is your obsessive-compulsive roommate who cleans up after you.</p><p>V8 uses an algorithm primarily based on <strong>Mark and Sweep</strong>. Here is how your roommate decides what stays and what goes</p><h3>The Roots (Entry Points)</h3><p>The roommate starts at the front door. In V8 terms, these are the <strong>Roots</strong>.</p><ul><li><p>The global object (<code>window</code> or <code>global</code>).</p></li><li><p>The current Call Stack (local variables in executing functions).</p></li></ul><h3>Reachability (The &#8220;Touch&#8221; Rule)</h3><p>The roommate walks through the house touching everything they can reach.</p><ol><li><p>They touch the Root (Global).</p></li><li><p>The Global object references a <code>User</code> object? They walk to the <code>User</code> object and touch it.</p></li><li><p>The <code>User</code> object references a <code>Profile</code>? They touch the <code>Profile</code>.</p></li></ol><p>This is the concept of <strong>Reachability</strong>. </p><p>If there is a chain of references (a path) from the Root to an object, that object is &#8220;Reachable.&#8221; It is marked as <strong>&#8220;Alive.&#8221;</strong></p><h3>The Sweep (The Trash)</h3><p>Once the roommate has traced every single path and marked every reachable item, they look at what&#8217;s left.</p><ul><li><p>That massive array you created inside a function that returned 5 minutes ago? No one is holding it.</p></li><li><p>That object you set to <code>null</code>? The path is broken.</p></li></ul><p>The roommate sweeps everything unmarked into the trash. <strong>Only now is the memory actually freed.</strong></p><h2>Generational Collection</h2><p>If the roommate checked every single item in the house every time they cleaned, your app would be agonizingly slow. </p><p>To solve this, V8 divides the Heap into two neighborhoods, <strong>The Young Generation (Nursery)</strong> and the <strong>Old Generation</strong>.</p><h3>Young Generation</h3><p>This is where all new objects are born. It is small (usually 1 to 8 MB).</p><p>High turnover. Most objects die young (temporary variables, loop iterators).</p><p>The GC runs a &#8220;Scavenge&#8221; (Minor GC) here very frequently. It is fast because most things here are dead anyway. It flips the survivors into a clean space and wipes the rest.</p><h3>The Old Generation</h3><p>If an object survives two cycles of Scavenging in the Nursery, the GC says, &#8220;Okay, this thing is sticking around.&#8221; It gets promoted (moved) to the Old Generation.</p><p>This is the attic. It&#8217;s huge (can be gigabytes).</p><p>Cleanup here is expensive.</p><h3>Stop-the-World Pauses</h3><p>Here is the nightmare scenario. </p><p>You keep promoting garbage to the Old Generation. The attic gets full.</p><p>When the Old Generation is saturated, the Scavenger can&#8217;t handle it. V8 has to call in the heavy machinery: <strong>The Major GC (Mark-Compact).</strong></p><p>To do this, V8 initiates a <strong>Stop-the-World</strong> pause.</p><p>It freezes your application. No click events. No server requests. No rendering.</p><p>The engine pauses execution to traverse the entire massive Old Heap, mark the living, and compact the memory to remove fragmentation.</p><p>If your user sees the UI stutter or your server drops a connection, it&#8217;s often because your roommate paused the world to clean up your mess.</p><h2>The &#8220;Bad Tenant&#8221; Behavior</h2><p>How do you saturate the Old Generation and cause these stutters? By being an unintentional hoarder.</p><h3>The Forgotten Timer</h3><pre><code><code>function startTracking() {
    const heavyObject = new Array(1000000); // 8MB
    setInterval(() =&gt; {
        // This callback references heavyObject
        console.log(heavyObject.length); 
    }, 1000);
}</code></code></pre><p>You ran <code>startTracking()</code> once. You forgot about it. </p><p>The <code>setInterval</code> references the callback. The callback references <code>heavyObject</code> (closure).</p><p>The result, a <code>heavyObject</code> is reachable from the Root (via the Timer). It survives the Nursery. It moves to Old Gen. It never dies.</p><h3>The Detached DOM Node</h3><p>You have a modal dialog.</p><pre><code><code>let myModal = document.getElementById('modal');
document.body.removeChild(myModal);</code></code></pre><p>You removed it from the DOM. The user can&#8217;t see it. The &#8220;Sweep&#8221; should pick it up, right?</p><p><strong>Wrong.</strong></p><p>The variable <code>myModal</code> still holds a reference to that DOM node in JavaScript memory. Even worse, if that DOM node has pointers to its children, you are keeping the entire tree alive in memory. </p><p>It is a &#8220;Detached Node&#8221;, a ghost haunting your heap.</p><h2>So what to do?</h2><p>Stop treating RAM like it&#8217;s infinite.</p><h3>Use WeakMap and WeakRef</h3><p>If you need to associate data with an object but don&#8217;t want that association to keep the object alive, use a <code>WeakMap</code>.</p><pre><code><code>let user = { name: "Alice" };
const cache = new WeakMap();

cache.set(user, "Some Metadata");

user = null; // The reference is broken.</code></code></pre><p>In a normal Map, <code>cache</code> would keep &#8220;Alice&#8221; alive. </p><p>In a <code>WeakMap</code>, the GC ignores the reference inside the map. </p><p>When <code>user</code> becomes unreachable elsewhere, the <code>WeakMap</code> entry is auto-deleted.</p><h3>Inspect the Snapshots</h3><p>Stop guessing. Open Chrome DevTools &#8594; <strong>Memory</strong> tab.</p><ol><li><p>Take a <strong>Heap Snapshot</strong>.</p></li><li><p>Run your action (open/close the modal).</p></li><li><p>Force a GC (click the trash can icon).</p></li><li><p>Take a second Snapshot.</p></li><li><p>Compare.</p></li></ol><p>If the Delta is positive and growing every time you repeat the action, you are leaking. </p><p>You are the bad tenant. </p><p>Clean up your room.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.binarybox.org/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">Thanks for reading BinaryBox! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p>]]></content:encoded></item><item><title><![CDATA[Thought - Why being Full Stack is making you Unemployable (Eventually)]]></title><description><![CDATA[If you describe yourself as a &#8220;Full Stack Developer&#8221; today you are putting a target on your back. You are positioning yourself as a generalist in a world that is rapidly automating general work.]]></description><link>https://www.binarybox.org/p/thought-why-being-full-stack-is-making</link><guid isPermaLink="false">https://www.binarybox.org/p/thought-why-being-full-stack-is-making</guid><dc:creator><![CDATA[Ashok Vishwakarma]]></dc:creator><pubDate>Thu, 05 Feb 2026 06:01:05 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Cj_u!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1b021d9-9af2-4970-a4e6-2d834bd4c4d4_678x381.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_!Cj_u!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1b021d9-9af2-4970-a4e6-2d834bd4c4d4_678x381.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Cj_u!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1b021d9-9af2-4970-a4e6-2d834bd4c4d4_678x381.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Cj_u!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1b021d9-9af2-4970-a4e6-2d834bd4c4d4_678x381.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Cj_u!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1b021d9-9af2-4970-a4e6-2d834bd4c4d4_678x381.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Cj_u!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1b021d9-9af2-4970-a4e6-2d834bd4c4d4_678x381.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Cj_u!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1b021d9-9af2-4970-a4e6-2d834bd4c4d4_678x381.jpeg" width="724" height="406.8495575221239" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e1b021d9-9af2-4970-a4e6-2d834bd4c4d4_678x381.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:381,&quot;width&quot;:678,&quot;resizeWidth&quot;:724,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;The six main causes of unhappy staff and job dissatisfaction | Edexec&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="The six main causes of unhappy staff and job dissatisfaction | Edexec" title="The six main causes of unhappy staff and job dissatisfaction | Edexec" srcset="https://substackcdn.com/image/fetch/$s_!Cj_u!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1b021d9-9af2-4970-a4e6-2d834bd4c4d4_678x381.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Cj_u!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1b021d9-9af2-4970-a4e6-2d834bd4c4d4_678x381.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Cj_u!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1b021d9-9af2-4970-a4e6-2d834bd4c4d4_678x381.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Cj_u!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1b021d9-9af2-4970-a4e6-2d834bd4c4d4_678x381.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>For the last ten years the industry has been obsessed with the myth of the <strong>Full Stack Engineer</strong>. Bootcamps sold the dream that you could learn React for three weeks and Node for three weeks and suddenly be a complete software engineer.</p><p>I am here to tell you that this era is ending.</p><p>If you describe yourself as a &#8220;Full Stack Developer&#8221; today you are putting a target on your back. You are positioning yourself as a generalist in a world that is rapidly automating general work. By trying to know a little bit of everything you are ensuring that you are not valuable at anything.</p><p>This is why the &#8220;Jack of All Trades&#8221; is about to become the &#8220;Master of None&#8221; and why specialization is the only safety net left.</p><h2>The AI is becoming the Ultimate Junior Generalist</h2><p>The primary reason the Full Stack role is dying is simple. <strong>Artificial Intelligence</strong>.</p><p>If your job consists of glueing a database to a frontend using standard frameworks you are in trouble. AI is starting to become exceptionally good at this. It can generate the boilerplate for a React form or a simple Express API in seconds.</p><p>The AI is the ultimate Full Stack Junior. It knows every framework. It knows every syntax. It can write the &#8220;glue code&#8221; faster than you ever will.</p><p>If your skillset is broad but shallow you are competing directly against a machine that works for free. The AI cannot yet debug a complex race condition in the Linux kernel. It cannot yet optimize a custom database engine for high frequency trading. But it can absolutely build a Todo App using the MERN stack. If that is your entire skillset you are a going to be replaced.</p><h2>Abstraction is Career Debt</h2><p>The rise of the Full Stack engineer coincided with the rise of massive abstraction. We have &#8220;Backend as a Service&#8221; and &#8220;Frontend as a Service&#8221; tools that hide all the complexity.</p><ul><li><p>You use Vercel so you do not need to understand servers.</p></li><li><p>You use Supabase so you do not need to understand database administration.</p></li><li><p>You use ORMs so you do not need to understand SQL.</p></li></ul><p>Every layer of abstraction you use without understanding the layer below it is <strong>Technical Debt</strong>. But it is not debt for your job. It is debt for your career.</p><p>When you rely entirely on tools to do the hard work you are leasing your skills instead of owning them. When the abstraction leaks (and it always does) you are helpless. A specialist knows what happens when the request hits the metal. A generalist only knows how to call the API.</p><h2>The T Shaped Lie</h2><p>We often tell engineers to be <strong>T Shaped</strong>. This means having broad knowledge across many areas (the top of the T) and deep knowledge in one specific area (the vertical line of the T).</p><p>This is good advice but most people are lying to themselves.</p><p>Most &#8220;Full Stack&#8221; engineers are not T Shaped. They are <strong>Dashes</strong>. They have a thin layer of knowledge across the top but they have no vertical depth.</p><ul><li><p>They know how to use an Index but they do not know how a B Tree works.</p></li><li><p>They know how to send an HTTP request but they do not know how a TCP handshake works.</p></li></ul><p>Being a Dash is dangerous. In a tight job market companies do not hire Dashes. They hire experts who can solve the expensive burning problems that the generalists caused.</p><h2>The Moat is Depth</h2><p>So how do you survive.</p><p>You must pick a hard problem and go deep.</p><p>Stop trying to keep up with every new JavaScript framework released this week. That is a treadmill that goes nowhere. Instead pick a foundational technology and master it.</p><ul><li><p>Become a database internalist. Learn how storage engines write to disk.</p></li><li><p>Become a networking specialist. Master the flow of packets and security protocols.</p></li><li><p>Become a graphics engineer. Learn the math behind the pixels.</p></li></ul><p>Depth cannot be prompted. AI relies on training data and the training data for deep complex edge cases is scarce. The generic code is abundant so the AI is good at it. The deep expert knowledge is rare so the AI is bad at it.</p><p>Your depth is your moat. Stop being Full Stack. Start being an Expert.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.binarybox.org/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">Thanks for reading BinaryBox! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p>]]></content:encoded></item><item><title><![CDATA[JavaScript - Holey Arrays vs. Packed Arrays]]></title><description><![CDATA[JavaScript arrays are not always arrays. Sometimes they are C-structs, sometimes they are Hash Maps. You control which one you get, often without realizing it.]]></description><link>https://www.binarybox.org/p/javascript-holey-arrays-vs-packed</link><guid isPermaLink="false">https://www.binarybox.org/p/javascript-holey-arrays-vs-packed</guid><dc:creator><![CDATA[Ashok Vishwakarma]]></dc:creator><pubDate>Tue, 03 Feb 2026 06:00:59 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!FwbJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bcfede6-fd27-4620-9f93-1a2ef2d51b31_1024x574.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_!FwbJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bcfede6-fd27-4620-9f93-1a2ef2d51b31_1024x574.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FwbJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bcfede6-fd27-4620-9f93-1a2ef2d51b31_1024x574.png 424w, https://substackcdn.com/image/fetch/$s_!FwbJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bcfede6-fd27-4620-9f93-1a2ef2d51b31_1024x574.png 848w, https://substackcdn.com/image/fetch/$s_!FwbJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bcfede6-fd27-4620-9f93-1a2ef2d51b31_1024x574.png 1272w, https://substackcdn.com/image/fetch/$s_!FwbJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bcfede6-fd27-4620-9f93-1a2ef2d51b31_1024x574.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!FwbJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bcfede6-fd27-4620-9f93-1a2ef2d51b31_1024x574.png" width="1024" height="574" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8bcfede6-fd27-4620-9f93-1a2ef2d51b31_1024x574.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:574,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:107070,&quot;alt&quot;:&quot;A Thorough Guide To JavaScript Array Methods with Examples - CoderPad&quot;,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="A Thorough Guide To JavaScript Array Methods with Examples - CoderPad" title="A Thorough Guide To JavaScript Array Methods with Examples - CoderPad" srcset="https://substackcdn.com/image/fetch/$s_!FwbJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bcfede6-fd27-4620-9f93-1a2ef2d51b31_1024x574.png 424w, https://substackcdn.com/image/fetch/$s_!FwbJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bcfede6-fd27-4620-9f93-1a2ef2d51b31_1024x574.png 848w, https://substackcdn.com/image/fetch/$s_!FwbJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bcfede6-fd27-4620-9f93-1a2ef2d51b31_1024x574.png 1272w, https://substackcdn.com/image/fetch/$s_!FwbJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bcfede6-fd27-4620-9f93-1a2ef2d51b31_1024x574.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>You see this code every day. You might have written it this morning.</p><pre><code><code>const arr = [1, 2, 3];
// ... some logic happens ...
arr[100] = 4; // The crime</code></code></pre><p>To a junior developer, this is the beauty of JavaScript, dynamic, flexible arrays that expand on demand. No <code>malloc</code>, no fixed sizes, no segmentation faults.</p><p>To a V8 engineer, this is a <strong>De-optimization Event</strong>.</p><p>By writing to index 100 of a 3-item array, you didn&#8217;t just add a number. You forced the engine to fundamentally alter the underlying storage structure of that object. You forced V8 to downgrade your high-performance memory block into a slow, lookup-heavy chain.</p><p>JavaScript arrays are not always arrays. Sometimes they are C-structs,  sometimes they are Hash Maps. You control which one you get, often without realizing it.</p><h2>Elements Kinds</h2><p>V8 tracks the shape of arrays using a system called <strong>Elements Kinds</strong>. There are over 20 distinct kinds, but for performance tuning, we care about the war between <code>PACKED</code> and <code>HOLEY</code>.</p><h3>The  <code>PACKED_SMI_ELEMENTS</code></h3><p>When you initialize <code>const arr = [1, 2, 3]</code>, V8 loves you. It detects that all elements are <strong>Small Integers (SMI)</strong> and the array is dense (no gaps).</p><p>Under the hood, this looks strikingly similar to a C++ <code>std::vector</code> or a raw C array.</p><ul><li><p><strong>Memory - </strong>Contiguous.</p></li><li><p><strong>Access - </strong>Simple pointer arithmetic. <code>Base Address + (Index * 4)</code>.</p></li><li><p><strong>Speed - </strong>O(1). Blazing fast.</p></li></ul><p>This is <code>PACKED_SMI_ELEMENTS</code>. This is where you want to stay.</p><h3>The Downgrade</h3><p>When you execute <code>arr[100] = 4</code>, you create a &#8220;hole&#8221;, a massive gap from index 3 to 99 where no data exists. V8 cannot rely on pointer arithmetic anymore because reading memory at offset 50 would return garbage or uninitialized memory.</p><p>The engine must reclassify the array. It transitions from <code>PACKED_SMI_ELEMENTS</code> to <code>HOLEY_SMI_ELEMENTS</code> (or <code>HOLEY_ELEMENTS</code> if types are mixed).</p><p>This is the most critical concept to internalize: <strong>Elements Kinds transitions are generally irreversible.</strong></p><p>Once an array becomes <code>HOLEY</code>, it stays <code>HOLEY</code>. Even if you backfill indices 3 through 99 later, V8 will not waste CPU cycles attempting to detect if the array is &#8220;healed&#8221; to switch it back to <code>PACKED</code>. You have permanently tainted the array&#8217;s performance profile for its entire lifecycle.</p><h2>Why Holey is Slow?</h2><p>Why does a hole matter? Why can&#8217;t the engine just return <code>undefined</code> for the gaps?</p><p>Because in JavaScript, <code>undefined</code><strong> is a value. A hole is the absence of a property.</strong></p><p>When you access <code>arr[50]</code> in a <code>HOLEY</code> array:</p><ul><li><p>V8 checks if index 50 exists on the array itself. It finds a hole.</p></li><li><p>V8 cannot simply return <code>undefined</code> yet. It must walk up the Prototype Chain (<code>Array.prototype</code>, then <code>Object.prototype</code>) to ensure that index 50 isn&#8217;t defined as a getter or value somewhere higher up.</p></li></ul><p>You turned a single memory fetch into a tree traversal.</p><h3>DICTIONARY_MODE</h3><p>The example above (<code>arr[100] = 4</code>) is bad, but manageable. However, if you do this</p><pre><code><code>const arr = [1, 2, 3];
arr[100000] = 4; // Sparse Array</code></code></pre><p>V8 looks at the memory waste required to allocate 100,000 empty slots for just two integers and decides to bail out entirely. It switches to <strong>DICTIONARY_MODE</strong>.</p><p>The array is no longer an array in memory. It becomes a <strong>Hash Map</strong>.</p><ul><li><p>Keys are converted to hashes.</p></li><li><p>Access becomes significantly slower due to hash computation and collision handling.</p></li><li><p>Iterating over this array is a performance disaster compared to a packed array.</p></li></ul><h2>The <code>new Array()</code></h2><p>I see this pattern in &#8220;optimized&#8221; codebases constantly</p><pre><code><code>// I am pre-allocating memory for performance
const arr = new Array(100); 
arr[0] = 1;</code></code></pre><p><strong>Stop doing this.</strong></p><p><code>new Array(100)</code> creates an array with <code>length: 100</code>, but <strong>zero allocated slots</strong>. It is born <code>HOLEY_SMI_ELEMENTS</code> (or <code>HOLEY_ELEMENTS</code>). You have pre-allocated nothing but a promise of slowness.</p><h3>How to fix that?</h3><p>If you want a packed array, you must ensure it has no holes from birth.</p><pre><code><code>// Use Literal (Best for small sets)
const arr = [1, 2, 3]; // PACKED_SMI_ELEMENTS</code></code></pre><pre><code><code>// Use Push (Best for Dynamic growth)
const arr = [];
for (let i = 0; i &lt; 100; i++) {
  arr.push(i); // Remains PACKED as it grows
}</code></code></pre><pre><code><code>// Use Array.from (A cleaner syntax)
// Creates a PACKED array filled with initialized values
const arr = Array.from({ length: 100 }, (_, i) =&gt; i); </code></code></pre><h2>Best Practices</h2><p>As senior engineers, we optimize for the machine, not just the linter.</p><h3>Never <code>delete</code> Array Elements</h3><p>Using the <code>delete</code> operator on an array index creates a hole.</p><pre><code><code>const arr = [1, 2, 3];
delete arr[1]; // Transitions to HOLEY_SMI_ELEMENTS
// arr is now [1, empty, 3]</code></code></pre><p>Use <code>.splice()</code> if you need to remove it, or overwrite it with a value if you need to maintain the index.</p><h3><code>undefined</code> is better than a Hole</h3><p>If you must &#8220;clear&#8221; a slot but keep the index, explicit <code>undefined</code> is superior to a hole.</p><pre><code><code>const arr = [1, 2, 3];
arr[1] = undefined; </code></code></pre><p>This transitions the array to <code>PACKED_ELEMENTS</code> (generic packed). While generic packed is slower than <code>PACKED_SMI</code> (because it has to handle tagging/boxing), it is significantly faster than <code>HOLEY</code> because it skips the prototype chain walk.</p><h3>Initialize Monomorphically</h3><p>Don&#8217;t mix types if you can avoid it.</p><ul><li><p><code>[1, 2, 3]</code> is <code>PACKED_SMI</code> (Fastest).</p></li><li><p><code>[1, 2, 3.5]</code> degrades to <code>PACKED_DOUBLE</code> (Fast, but requires conversion overhead).</p></li><li><p><code>[1, 2, '3']</code> degrades to <code>PACKED_ELEMENTS</code> (Slower).</p></li></ul><p>Treat your arrays like static memory blocks. Keep them contiguous, keep them typed, and never let V8 doubt the integrity of your indices.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.binarybox.org/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">Thanks for reading BinaryBox! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[The Lie of the JavaScript Object]]></title><description><![CDATA[If you do not understand how Shapes work you are writing code that forces the engine to abandon its optimizations and fall back to the slow path.]]></description><link>https://www.binarybox.org/p/the-lie-of-the-javascript-object</link><guid isPermaLink="false">https://www.binarybox.org/p/the-lie-of-the-javascript-object</guid><dc:creator><![CDATA[Ashok Vishwakarma]]></dc:creator><pubDate>Thu, 29 Jan 2026 06:01:20 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!OJYE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde1ecb83-e434-4ea2-a890-f9091179e63f_1920x1080.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_!OJYE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde1ecb83-e434-4ea2-a890-f9091179e63f_1920x1080.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!OJYE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde1ecb83-e434-4ea2-a890-f9091179e63f_1920x1080.png 424w, https://substackcdn.com/image/fetch/$s_!OJYE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde1ecb83-e434-4ea2-a890-f9091179e63f_1920x1080.png 848w, https://substackcdn.com/image/fetch/$s_!OJYE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde1ecb83-e434-4ea2-a890-f9091179e63f_1920x1080.png 1272w, https://substackcdn.com/image/fetch/$s_!OJYE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde1ecb83-e434-4ea2-a890-f9091179e63f_1920x1080.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!OJYE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde1ecb83-e434-4ea2-a890-f9091179e63f_1920x1080.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/de1ecb83-e434-4ea2-a890-f9091179e63f_1920x1080.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;What is the global object in JavaScript? A practical guide for developers |  Contentful&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="What is the global object in JavaScript? A practical guide for developers |  Contentful" title="What is the global object in JavaScript? A practical guide for developers |  Contentful" srcset="https://substackcdn.com/image/fetch/$s_!OJYE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde1ecb83-e434-4ea2-a890-f9091179e63f_1920x1080.png 424w, https://substackcdn.com/image/fetch/$s_!OJYE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde1ecb83-e434-4ea2-a890-f9091179e63f_1920x1080.png 848w, https://substackcdn.com/image/fetch/$s_!OJYE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde1ecb83-e434-4ea2-a890-f9091179e63f_1920x1080.png 1272w, https://substackcdn.com/image/fetch/$s_!OJYE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fde1ecb83-e434-4ea2-a890-f9091179e63f_1920x1080.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>Consider this line of code.</p><pre><code><code>const point = { x: 1, y: 2 };</code></code></pre><p>Ask a developer what this is and if they will tell you it is a dictionary or a hash map. They will tell you that <code>x</code> and <code>y</code> are string keys that map to values and looking them up requires a hash calculation.</p><p><strong>They are wrong.</strong></p><p>To the V8 engine (which powers Chrome and Node.js) treating this object as a hash map is a failure state. </p><p>A hash map is slow. It involves computing a hash handling collisions and chasing pointers. </p><p>V8 wants speed. It wants to access <code>point.x</code> with a single machine instruction just like a C++ struct.</p><p>To achieve this V8 relies on a hidden machinery called <strong>Shapes</strong> (often called Hidden Classes or Maps). </p><p>If you do not understand how Shapes work you are writing code that forces the engine to abandon its optimizations and fall back to the slow path.</p><p>This article will tear down the abstraction of the JavaScript Object and reveal the transition trees and inline caches that live underneath.</p><h2>What is a Shape?</h2><p>JavaScript is a dynamic language. You can add or remove properties at runtime. </p><p>C++ is a static language. The memory layout is fixed at compile time. </p><p>V8 is a bridge that tries to make the former behave like the latter.</p><p>When you create an object V8 does not just allocate a bucket for keys and values. It allocates a <strong>Shape</strong>.</p><p>A <strong>Shape</strong> is a metadata descriptor. It contains</p><ol><li><p>The property names (e.g. &#8220;x&#8221;).</p></li><li><p>The attributes of those properties (writable enumerable etc.).</p></li><li><p>Crucially <strong>The Offset</strong> where the value is stored in memory.</p></li></ol><h3>The Transition Tree</h3><p>V8 builds these Shapes dynamically as you mutate objects. Let us trace the creation of our point object.</p><h4><code>const point = {}; </code></h4><p>V8 starts with the <strong>Root Shape</strong> (Empty).</p><h4><code>point.x = 1;</code></h4><p>V8 sees a new property <code>x</code>. It cannot fit this into the Root Shape. It creates a new Shape (Shape A) that says &#8220;Offset 0 contains x&#8221;. It links the Root Shape to Shape A via a <strong>Transition</strong> (If you are at Root and add &#8216;x&#8217; go to Shape A).</p><h4><code>point.y = 2;</code></h4><p>V8 sees <code>y</code>. It transitions from Shape A to Shape B. Shape B says &#8220;Offset 0 is x, Offset 1 is y&#8221;.</p><p>Now when you access <code>point.y</code> V8 does not calculate the hash of the string &#8220;y&#8221;. It looks at the Shape sees that <code>y</code> is at Offset 1 and reads the memory directly. </p><p>This is near-native speed.</p><h2>The Performance Killer (Polymorphism)</h2><p>The system works perfectly as long as your objects share the same Shape. But developers often break this mechanism without realizing it.</p><p>Consider these two objects</p><pre><code><code>// Path 1
const a = {};
a.x = 1;
a.y = 2;

// Path 2
const b = {};
b.y = 2;
b.x = 1;</code></code></pre><p>To a developer <code>a</code> and <code>b</code> are identical. They both have <code>x</code> and <code>y</code>.</p><p>But to V8 they are completely different entities.</p><p>Object <code>a</code> followed the transition chain, Empty -&gt; Add x -&gt; Add y. It creates <strong>Shape ID 1</strong>.</p><p>Object <code>b</code> followed the transition chain, Empty -&gt; Add y -&gt; Add x. It creates <strong>Shape ID 2</strong>.</p><p>Because the properties were initialized in a different order the offsets are different. In <code>a</code>, <code>x</code> is at offset 0. In <code>b</code>, <code>x</code> is at offset 1.</p><h3>The Inline Cache (IC) Fail</h3><p>This matters because of the <strong>Inline Cache</strong>.</p><p>When V8 runs a function that reads <code>obj.x</code> it &#8220;learns&#8221; the Shape of the object passed to it.</p><pre><code><code>function getX(obj) {
    return obj.x;
}</code></code></pre><h4>Monomorphic State (Fastest)</h4><p>If you always pass objects with <strong>Shape ID 1</strong> V8 compiles a hot path. It says &#8220;I know this shape. <code>x</code> is always at offset 0. Just load memory index 0.&#8221; It strips out all checks. </p><p>This is the <strong>Monomorphic</strong> state.</p><h4>Polymorphic State (Slower)</h4><p>If you pass <code>a</code> (Shape 1) and then <code>b</code> (Shape 2) V8 invalidates the optimized code. It switches to a <strong>Polymorphic</strong> state. </p><p>It generates code that looks like a <code>switch</code> statement</p><ul><li><p>&#8220;If Shape 1 load offset 0.&#8221;</p></li><li><p>&#8220;If Shape 2 load offset 1.&#8221; This adds CPU cycles for branching and checking.</p></li></ul><h4>Megamorphic State (The Cliff)</h4><p>If you pass objects with 5 or more different Shapes (e.g. created via random assignment loops) V8 gives up. </p><p>It marks the call site as <strong>Megamorphic</strong>. </p><p>It stops trying to optimize offsets. </p><p>It falls back to <strong>Dictionary Mode</strong>. </p><p>It effectively treats the object as a hash map and performs a slow lookup for every single access. Your performance just fell off a cliff.</p><div><hr></div><h2>Takeaway</h2><p><strong>Static Initialization is King.</strong></p><p>You cannot control the V8 compiler but you can control the Shapes it generates.</p><h4>Initialize Properties in the Same Order</h4><p>Always write your keys in the same sequence, here is a bad example of the same</p><pre><code><code>if (condition) { 
  obj.a = 1; 
  obj.b = 2; 
} else { 
  obj.b = 2; 
  obj.a = 1; 
}</code></code></pre><p>The good way to ensuring the transition path is deterministic.</p><h4>Use Object Literals or Constructor</h4><p>Using </p><p><code>class Point { constructor(x,y) { this.x = x; this.y = y; } }</code></p><p>guarantees that every instance follows the exact same transition chain.</p><p>Piecemeal assignment (<code>obj.a = ...</code>) is risky.</p><h4>Avoid <code>delete</code></h4><p>Using the <code>delete</code> keyword typically forces V8 to abandon the Shape optimization entirely and revert the object to Dictionary Mode because the transition tree does not support &#8220;removing&#8221; a step efficiently. </p><p>If you need to remove a value set it to <code>null</code> or <code>undefined</code> instead.</p><p>You are not writing JavaScript for a browser. </p><p>You are writing JavaScript for a JIT compiler. </p><p>Treat your objects like Structs and the engine will reward you with C++ performance. </p><p>Treat them like Hash Maps and you will pay the dynamic language tax.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.binarybox.org/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">Thanks for reading BinaryBox! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Database - The cost of using UUID as Primary Key]]></title><description><![CDATA[When you make UUIDv4 your Primary Key you are making a decision that fights against the fundamental physics of how databases store data.]]></description><link>https://www.binarybox.org/p/database-the-cost-of-using-uuid-as</link><guid isPermaLink="false">https://www.binarybox.org/p/database-the-cost-of-using-uuid-as</guid><dc:creator><![CDATA[Ashok Vishwakarma]]></dc:creator><pubDate>Wed, 28 Jan 2026 09:40:52 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!j0_-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0ac9b2d-7b17-47d2-b0c8-dfd1fccb0905_1558x696.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_!j0_-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0ac9b2d-7b17-47d2-b0c8-dfd1fccb0905_1558x696.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!j0_-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0ac9b2d-7b17-47d2-b0c8-dfd1fccb0905_1558x696.png 424w, https://substackcdn.com/image/fetch/$s_!j0_-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0ac9b2d-7b17-47d2-b0c8-dfd1fccb0905_1558x696.png 848w, https://substackcdn.com/image/fetch/$s_!j0_-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0ac9b2d-7b17-47d2-b0c8-dfd1fccb0905_1558x696.png 1272w, https://substackcdn.com/image/fetch/$s_!j0_-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0ac9b2d-7b17-47d2-b0c8-dfd1fccb0905_1558x696.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!j0_-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0ac9b2d-7b17-47d2-b0c8-dfd1fccb0905_1558x696.png" width="1558" height="696" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d0ac9b2d-7b17-47d2-b0c8-dfd1fccb0905_1558x696.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:696,&quot;width&quot;:1558,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:123755,&quot;alt&quot;:&quot;Database Design Bad Practices | Toptal&#174;&quot;,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Database Design Bad Practices | Toptal&#174;" title="Database Design Bad Practices | Toptal&#174;" srcset="https://substackcdn.com/image/fetch/$s_!j0_-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0ac9b2d-7b17-47d2-b0c8-dfd1fccb0905_1558x696.png 424w, https://substackcdn.com/image/fetch/$s_!j0_-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0ac9b2d-7b17-47d2-b0c8-dfd1fccb0905_1558x696.png 848w, https://substackcdn.com/image/fetch/$s_!j0_-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0ac9b2d-7b17-47d2-b0c8-dfd1fccb0905_1558x696.png 1272w, https://substackcdn.com/image/fetch/$s_!j0_-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0ac9b2d-7b17-47d2-b0c8-dfd1fccb0905_1558x696.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>We love UUIDs. They seduce us with a simple promise. You can generate a globally unique ID on a client device without talking to a database. You can merge records from ten different distributed systems without a single collision. They are stateless. They are easy.</p><p>But in the world of database design convenience usually comes with a tax.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.binarybox.org/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">Thanks for reading BinaryBox! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>When you make <code>UUIDv4</code> your Primary Key you are making a decision that fights against the fundamental physics of how databases store data. You are choosing randomness. And in a B-Tree <strong>randomness is the enemy of locality</strong>.</p><p>This article will explain why your &#8220;lazy default&#8221; is causing your database to burn IOPS, trash its buffer pool and bloat your storage.</p><h2>The B-Tree</h2><p>To understand why UUID v4 is dangerous we have to look at the data structure that powers your database index the <strong>B-Tree</strong> (or B+Tree).</p><p>A B-Tree is designed for one specific goal <strong>Locality</strong>. It wants to store related data close together on the physical disk. </p><p>When you request Record 100 the database loads a &#8220;Page&#8221; (usually 8KB or 16KB) of data into memory. Because of locality that page likely also contains Record 99 and Record 101. This makes range scans and sequential reads blazing fast.</p><p>To maintain this locality the B-Tree must be <strong>Sorted</strong>.</p><h3>The Sequential Insert</h3><p>When you insert sequential IDs (like <code>1 2 3</code> or <code>Timestamp</code>) the database behaves like a logger. It simply adds new entries to the end of the file.</p><ol><li><p><strong>Locality</strong> - The database only needs to access the <strong>Rightmost</strong> page of the index. This page is &#8220;hot&#8221; (already in RAM).</p></li><li><p><strong>Fill Factor</strong> - The database fills the page to 100% capacity, closes it, saves it to disk, and allocates a new empty page.</p></li><li><p><strong>Result</strong> - Zero wasted space. Minimal disk movement.</p></li></ol><p>This is the &#8220;Easy Mode&#8221; for any storage engine.</p><h3>The Random Insert</h3><p>Now imagine inserting a random UUID v4. <code>a902...</code> arrives.</p><p>This ID might have been generated on a user&#8217;s phone milliseconds ago or hours ago while offline. To the database time does not matter. Only the <strong>Value</strong> matters.</p><p>Even though this is a &#8220;new&#8221; record (inserted <em>now</em>) its <strong>Value</strong> (<code>a902...</code>) might be lexicographically smaller than records you created yesterday (e.g. <code>b100...</code>).</p><p>A B-Tree is strictly sorted by Value. The database cannot just append <code>a902...</code> to the end. It effectively says</p><p><em>&#8220;Oh based on alphabetical order this new book belongs on a specific shelf that I filled up and sealed three days ago.&#8221;</em></p><p>It forces the database to go back in time fetch that old &#8220;cold&#8221; page from the disk and try to shove the new data in. This triggers the mechanical disaster.</p><h2>The Page Splitting Problem</h2><p>The database fetches that old page from the disk into the Buffer Pool (memory). It tries to insert the new UUID.</p><p><strong>The Problem</strong>, the page is full.</p><p>To make room for this random entry the database performs a <strong>Page Split</strong>.</p><ol><li><p>It allocates a new empty page.</p></li><li><p>It takes half the records from the old page and moves them to the new page.</p></li><li><p>It inserts the new UUID into the middle.</p></li><li><p>It updates the parent pointer nodes to reflect the new path.</p></li></ol><p>This has some consequences,</p><h3>Write Amplification</h3><p>You wanted to write 32 bytes of data. But to do it the database had to load a 16KB page create another 16KB page and write both back to disk. </p><p>You are burning CPU and I/O bandwidth just to move data around.</p><h3>Buffer Pool Thrashing</h3><p>In a sequential insert you only need the &#8220;latest&#8221; page in memory. In a random insert any page from the entire history of your database might be needed at any moment. </p><p>This defeats your caching strategy. Your Buffer Pool churns constantly evicting &#8220;hot&#8221; data to load &#8220;cold&#8221; pages just to insert a random ID.</p><h3>Fragmentation and Disk Bloat</h3><p>After a split you are left with two pages that are only 50% full. If you keep inserting randomly your pages effectively stay half empty. </p><p>This means your index takes up <strong>2x more disk space</strong> than a sequential index. This is not just a storage cost issue. </p><p>It means your RAM can only hold half as many keys leading to even more disk reads.</p><h2>UUID v4 vs BigInt vs UUID v7</h2><p>UUIDv4  is the standard 128-bit random identifier. Its globally unique and required coordination.</p><p>But, destroys B-Tree performance. Fragments indexes. Clogs the WAL (Write Ahead Log) because page splits create massive log records.</p><p>So if UUID v4 is the villain who is the hero?</p><h3>BigInt or Serial</h3><p>The classic auto-incrementing integer.</p><p><strong>Extremely fast sequential inserts. 64-bit size (half the size of a UUID).</strong></p><p>But, it leaks business intelligence. If I create a user and get ID <code>105</code> and create another tomorrow and get <code>150</code> I know you only grew by 45 users. </p><p>It is also painful in active-active distributed systems where two servers might generate ID <code>106</code> at the same time.</p><h3>UUID v7</h3><p>Approved in 2024 this standard is designed specifically to solve the DB problem.</p><p>It embeds a <strong>48-bit Timestamp</strong> at the start of the ID followed by random bits.</p><p>Because the start of the ID is time-based new records are generated in (mostly) increasing order.</p><p>To the B-Tree a UUID v7 looks like a sequential integer. It appends to the right. It fills pages completely. It avoids splitting. But it retains the distributed uniqueness and unguessability of a UUID.</p><div><hr></div><p>I was once called in to consult for a logistics company. They had an event logging system that tracked packages. The system was simple. Every scan event got a UUID v4 Primary Key.</p><p>For the first year it was fine. Then they hit <strong>50 Million Rows</strong>.</p><p>The Write Latency spiked from 2ms to 200ms. CPU usage on the RDS instance sat at 90%. They upgraded the instance class twice doubling their bill but the CPU didn&#8217;t drop.</p><p>After looking into the database memory I found, rhe dataset size had finally exceeded the available RAM (Buffer Pool). </p><p>When the table was small the entire B-Tree lived in memory. Random inserts were just RAM operations.</p><p>The moment the index grew larger than RAM every random insert became a <strong>Disk Read</strong>. To insert a record the DB had to fetch a random cold page from disk to memory.</p><p>For the fix, we couldn&#8217;t migrate the primary keys easily. Instead we introduced a <strong>composite sort key</strong> using a timestamp and rebuilt the clustered index to follow time rather than the UUID. </p><p>The UUID remained unique but it no longer dictated the physical storage order. Writes dropped back to 5ms. CPU dropped to 10%.</p><div><hr></div><h2>Conclusion</h2><p>We are not guessing here. The benchmarks are clear. In tests inserting 100 million rows</p><ul><li><p><strong>UUID v4</strong> takes <strong>2x to 3x longer</strong> than sequential IDs.</p></li><li><p><strong>UUID v4</strong> indexes are <strong>30% to 50% larger</strong> due to fragmentation.</p></li><li><p><strong>UUID v7</strong> performance is nearly identical to BigInt sequential inserts.</p></li></ul><p>So, stop using UUID v4 for database Primary Keys. It is a legacy default that ignores computer science fundamentals.</p><ul><li><p>If you need simple internal speed use <strong>BigInt</strong>.</p></li><li><p>If you need distributed scale and public safety use <strong>UUID v7</strong>.</p></li><li><p>Only use <strong>UUID v4</strong> for ephemeral tokens or trace IDs that are never indexed.</p></li></ul><p>Don&#8217;t let randomness kill your locality.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.binarybox.org/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">Thanks for reading BinaryBox! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item></channel></rss>