<?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[DE's Notes & Thoughts: System Design]]></title><description><![CDATA[Observations on architecture, patterns and real-world scenarios]]></description><link>https://blog.diana-enache.com/s/system-design</link><image><url>https://substackcdn.com/image/fetch/$s_!R5Si!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6b4625c-aab8-4926-be6c-35b6b1b5b802_500x500.png</url><title>DE&apos;s Notes &amp; Thoughts: System Design</title><link>https://blog.diana-enache.com/s/system-design</link></image><generator>Substack</generator><lastBuildDate>Mon, 04 May 2026 22:14:44 GMT</lastBuildDate><atom:link href="https://blog.diana-enache.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Diana Darie]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[theengineeringcompass@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[theengineeringcompass@substack.com]]></itunes:email><itunes:name><![CDATA[Diana Darie]]></itunes:name></itunes:owner><itunes:author><![CDATA[Diana Darie]]></itunes:author><googleplay:owner><![CDATA[theengineeringcompass@substack.com]]></googleplay:owner><googleplay:email><![CDATA[theengineeringcompass@substack.com]]></googleplay:email><googleplay:author><![CDATA[Diana Darie]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Building an Audit Logging Solution: Production Scars and Evolutionary Architectures]]></title><description><![CDATA[On lessons learnt when mvps and balancing trade offs aren't enough]]></description><link>https://blog.diana-enache.com/p/building-an-audit-logging-solution</link><guid isPermaLink="false">https://blog.diana-enache.com/p/building-an-audit-logging-solution</guid><dc:creator><![CDATA[Diana Darie]]></dc:creator><pubDate>Wed, 18 Dec 2024 14:59:19 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/70bb2644-5d26-4484-935d-6db5619390c7_4194x1892.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>System design is making tough trade offs and understanding why one approach is better than another. Sometimes this decision ends up being the wrong one. So you need to live with the consequences and make another trade off, do you start from scratch and take another approach or do you live with a not so perfect solution?</p><p>As reflection is an essential part of the learning process, this article is all about acknowledging that even with the right intentions and much dedication, you don&#8217;t always get it right. This is about accepting this reality and reminding myself that growth is a learning curve and despite setbacks we need to continue to take ownership.</p><div><hr></div><h3>What problem did we try to solve?</h3><p>Maintaining accountability within data-driven systems along with keeping track of who did what and when within isn't just a security requirement&#8212;sometimes it's a crucial business necessity. Whether if it&#8217;s just for meeting compliance requirements, troubleshooting and understanding system behaviour, investigating production incidents or providing insights for post-mortem analysis, a robust audit logging solution serves as your system's source of truth.</p><p>But building such a solution comes with a lot of challenges in terms of scalability, performance and most of all, data integrity. In this article, we&#8217;ll explore what are the possible approaches to implement such a system that captures meaningful events, stores them reliably, and makes them easily accessible when you need them most. We'll cover the essential components that make up a production-grade audit logging solution and emphasise some lessons learnt from implementing a &#8220;tamper-proof solution&#8221;.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fqAS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16e16e2f-01b5-40cf-b827-e07919b1a84e_583x428.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fqAS!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16e16e2f-01b5-40cf-b827-e07919b1a84e_583x428.png 424w, https://substackcdn.com/image/fetch/$s_!fqAS!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16e16e2f-01b5-40cf-b827-e07919b1a84e_583x428.png 848w, https://substackcdn.com/image/fetch/$s_!fqAS!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16e16e2f-01b5-40cf-b827-e07919b1a84e_583x428.png 1272w, https://substackcdn.com/image/fetch/$s_!fqAS!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16e16e2f-01b5-40cf-b827-e07919b1a84e_583x428.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fqAS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16e16e2f-01b5-40cf-b827-e07919b1a84e_583x428.png" width="451" height="331.0943396226415" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/16e16e2f-01b5-40cf-b827-e07919b1a84e_583x428.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:428,&quot;width&quot;:583,&quot;resizeWidth&quot;:451,&quot;bytes&quot;:null,&quot;alt&quot;:null,&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="" srcset="https://substackcdn.com/image/fetch/$s_!fqAS!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16e16e2f-01b5-40cf-b827-e07919b1a84e_583x428.png 424w, https://substackcdn.com/image/fetch/$s_!fqAS!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16e16e2f-01b5-40cf-b827-e07919b1a84e_583x428.png 848w, https://substackcdn.com/image/fetch/$s_!fqAS!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16e16e2f-01b5-40cf-b827-e07919b1a84e_583x428.png 1272w, https://substackcdn.com/image/fetch/$s_!fqAS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16e16e2f-01b5-40cf-b827-e07919b1a84e_583x428.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><h3>What is an audit log? </h3><p>We want to know all database interactions that happened during a period of time, along with detailed information about each event. Those logs should be queryable and be able to answer questions like "who changed this value" or "which process caused this item to be removed." <strong>Audit logs</strong> record the occurrence of an <strong>event</strong>, the <strong>time</strong> at which it occurred, the responsible <strong>user</strong> or <strong>service</strong>, and the impacted <strong>entity</strong>.</p><p>A good audit logging system should not only record event data but also consider various usability criteria for the teams inspecting the logs (i.e the end users) and the future maintainers (e.g. engineers) of the system. The main requirements we&#8217;re going to work with: </p><ul><li><p>audit logs should be<strong> reliable</strong> - any database change should have a corresponding audit log entry.</p></li><li><p>have <strong>no</strong> or <strong>minimal</strong> <strong>setup </strong>- should be easy to set up across the ecosystem and ideally require no or minimal code changes for new services.</p></li><li><p>audit logs should be<strong> immutable - </strong>users and services should only have the ability to read data the logs and not update them.</p></li><li><p>audit logs should be <strong>easily queryable</strong> (by service, action, date, user etc) - users must be able to efficiently search through the logs by applying any one or more filters.</p></li><li><p>audit logs should be<strong> parsable</strong> - logs should also be easy to parse and work with. </p></li></ul><p>Since the ecosystem we work with is only using DynamoDB as a storage option, we&#8217;ll design the audit log solution to work especially with this kind of database. </p><h3>Solutions Considered </h3><p><strong>1. via the Transactional Outbox Pattern</strong></p><p>One solution to implement the audit logs would be to emit an event with every database change. This event would contain all the necessary information to track the change (what got changed, who changed it etc). The consumer of those events would process the data and store it in a way that would be easily accessible and queryable by all devs. </p><p>In our current ecosystem, we use an internal library go-kit (similar to the <a href="https://github.com/go-kit/kit">open source one go-kit</a>) to help us with the scaffolding and management of our golang microservices. This library also provides a standardised way for doing all db interactions. This approach would mean just modifying this library to emit an event when doing a CRUD operation. The advantage would be services don&#8217;t need to be  aware of this logic and no logic would need to be updated.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Wo5S!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3634b637-9adc-4ba7-b208-83ff153d2c13_1653x1742.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Wo5S!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3634b637-9adc-4ba7-b208-83ff153d2c13_1653x1742.png 424w, https://substackcdn.com/image/fetch/$s_!Wo5S!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3634b637-9adc-4ba7-b208-83ff153d2c13_1653x1742.png 848w, https://substackcdn.com/image/fetch/$s_!Wo5S!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3634b637-9adc-4ba7-b208-83ff153d2c13_1653x1742.png 1272w, https://substackcdn.com/image/fetch/$s_!Wo5S!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3634b637-9adc-4ba7-b208-83ff153d2c13_1653x1742.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Wo5S!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3634b637-9adc-4ba7-b208-83ff153d2c13_1653x1742.png" width="500" height="526.7857142857143" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3634b637-9adc-4ba7-b208-83ff153d2c13_1653x1742.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1534,&quot;width&quot;:1456,&quot;resizeWidth&quot;:500,&quot;bytes&quot;:168358,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Wo5S!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3634b637-9adc-4ba7-b208-83ff153d2c13_1653x1742.png 424w, https://substackcdn.com/image/fetch/$s_!Wo5S!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3634b637-9adc-4ba7-b208-83ff153d2c13_1653x1742.png 848w, https://substackcdn.com/image/fetch/$s_!Wo5S!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3634b637-9adc-4ba7-b208-83ff153d2c13_1653x1742.png 1272w, https://substackcdn.com/image/fetch/$s_!Wo5S!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3634b637-9adc-4ba7-b208-83ff153d2c13_1653x1742.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">A possible design for the audit log solution where we emit an event for every CRUD operation</figcaption></figure></div><p>The problem with this solution is the general <em>dual-write issue</em> where you want to make 2 write operations in one atomic transaction. If we want to update 2 different systems, persist data in the database and send an event to notify other systems, because these two systems aren't linked, we have no way to update both in a transactional fashion. When a microservice sends an event notification after a database update, these two operations should run atomically to ensure data consistency and reliability.</p><p>The way to solve this is usually through the Outbox Pattern. If we have a database that supports transactional updates, then we can use it to overcome the dual-write problem. In our case, we would need another table, say an &#8220;Outbox Table&#8220;, and on a DB CRUD operation we would 1. do the CRUD operation and 2. save the change we did in the outbox table (both as part of a transaction which DynamoDB supports). The records in the outbox table will then be read by some workers which will emit an event with the changed data. The events will be read by an &#8220;Auditor Service&#8220; that will process them and finally store them in a queryable way.</p><p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FS9r!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F378dc940-3b7b-4689-a3e7-fc82b4016cdb_1394x1282.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FS9r!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F378dc940-3b7b-4689-a3e7-fc82b4016cdb_1394x1282.png 424w, https://substackcdn.com/image/fetch/$s_!FS9r!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F378dc940-3b7b-4689-a3e7-fc82b4016cdb_1394x1282.png 848w, https://substackcdn.com/image/fetch/$s_!FS9r!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F378dc940-3b7b-4689-a3e7-fc82b4016cdb_1394x1282.png 1272w, https://substackcdn.com/image/fetch/$s_!FS9r!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F378dc940-3b7b-4689-a3e7-fc82b4016cdb_1394x1282.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!FS9r!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F378dc940-3b7b-4689-a3e7-fc82b4016cdb_1394x1282.png" width="634" height="583.0616929698708" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/378dc940-3b7b-4689-a3e7-fc82b4016cdb_1394x1282.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1282,&quot;width&quot;:1394,&quot;resizeWidth&quot;:634,&quot;bytes&quot;:130971,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!FS9r!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F378dc940-3b7b-4689-a3e7-fc82b4016cdb_1394x1282.png 424w, https://substackcdn.com/image/fetch/$s_!FS9r!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F378dc940-3b7b-4689-a3e7-fc82b4016cdb_1394x1282.png 848w, https://substackcdn.com/image/fetch/$s_!FS9r!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F378dc940-3b7b-4689-a3e7-fc82b4016cdb_1394x1282.png 1272w, https://substackcdn.com/image/fetch/$s_!FS9r!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F378dc940-3b7b-4689-a3e7-fc82b4016cdb_1394x1282.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">An audit log solution based on the outbox pattern approach</figcaption></figure></div><p>This approach comes with a fair bit of complexities. We would have at least one other table (we can choose to use one single outbox table for all services or create a seperate outbox table for each service). We would introduce some latency due to the additional database write for every transaction (to outbox). There is also the consideration of how we&#8217;re going to manage the outbox table growth/cleanup. We would need to think how to coordinate the allocation of work between the worker services. </p><p><strong>2. via the CDC Approach</strong></p><p>A second solution would be relying on a Change Data Capture (CDC) approach. CDC is <em>the process of identifying and capturing changes made to data in a database and then delivering those changes in real-time to a downstream process or system</em>). The basic idea is that we will store our data to a storage that supports CDC. Then the CDC infrastructure will notify external systems of the changes. Fortunately for us, DynamoDB provides such an option, called <strong>DynamoDB Streams.</strong></p><p>DynamoDB Streams captures a time-ordered sequence of item-level modifications in any DynamoDB table and stores this information in a log for up to 24 hours (can be extended to 7 days). Applications can access this log and view the data items as they appeared before and after they were modified, in near-real time.</p><p>At first glance this approach sounds like a good solution for our use case. No other resources are required to be setup. DynamoDB provides a CDC capability out of the box. Scalability and reliability are provided natively by AWS. The code what we would need to add would be minimal as we just need a service which reads the data from the dynamodb streams. So we went ahead with this. </p><h3>What&#8217;s in a DynamoDB Stream?</h3><p>Any dynamodb table with dynamodb streams enabled can have one dynamodb stream active. At any point in time, we can only have one active stream. A stream can have multiple shards. A shard can contain zero or more records. A record is the change that we want to be captured.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!lWmO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5fe887e-b3ee-40f6-8b3c-454ae450cb23_3485x1200.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lWmO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5fe887e-b3ee-40f6-8b3c-454ae450cb23_3485x1200.png 424w, https://substackcdn.com/image/fetch/$s_!lWmO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5fe887e-b3ee-40f6-8b3c-454ae450cb23_3485x1200.png 848w, https://substackcdn.com/image/fetch/$s_!lWmO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5fe887e-b3ee-40f6-8b3c-454ae450cb23_3485x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!lWmO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5fe887e-b3ee-40f6-8b3c-454ae450cb23_3485x1200.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!lWmO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5fe887e-b3ee-40f6-8b3c-454ae450cb23_3485x1200.png" width="3485" height="1200" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b5fe887e-b3ee-40f6-8b3c-454ae450cb23_3485x1200.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1200,&quot;width&quot;:3485,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:188180,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!lWmO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5fe887e-b3ee-40f6-8b3c-454ae450cb23_3485x1200.png 424w, https://substackcdn.com/image/fetch/$s_!lWmO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5fe887e-b3ee-40f6-8b3c-454ae450cb23_3485x1200.png 848w, https://substackcdn.com/image/fetch/$s_!lWmO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5fe887e-b3ee-40f6-8b3c-454ae450cb23_3485x1200.png 1272w, https://substackcdn.com/image/fetch/$s_!lWmO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5fe887e-b3ee-40f6-8b3c-454ae450cb23_3485x1200.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Overview of the DynamoDB Stream Components</figcaption></figure></div><p>Depending on how the stream was set up when it was enabled, the shard record can contain different types of data (<a href="https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_StreamSpecification.html">source</a>): </p><ul><li><p><code>KEYS_ONLY</code> - Only the key attributes of the modified item are written to the stream.</p></li><li><p><code>NEW_IMAGE</code> - The entire item, as it appears after it was modified, is written to the stream.</p></li><li><p><code>OLD_IMAGE</code> - The entire item, as it appeared before it was modified, is written to the stream.</p></li><li><p><code>NEW_AND_OLD_IMAGES</code> - Both the new and the old item images of the item are written to the stream.</p></li></ul><p>We&#8217;re interested in the last type, <code>NEW_AND_OLD_IMAGES</code>, and so in our case, we&#8217;re expecting our record to look similar to the following:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NK-U!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f6bd9e3-0975-4627-bd44-6e1c003bfa62_1596x1514.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NK-U!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f6bd9e3-0975-4627-bd44-6e1c003bfa62_1596x1514.png 424w, https://substackcdn.com/image/fetch/$s_!NK-U!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f6bd9e3-0975-4627-bd44-6e1c003bfa62_1596x1514.png 848w, https://substackcdn.com/image/fetch/$s_!NK-U!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f6bd9e3-0975-4627-bd44-6e1c003bfa62_1596x1514.png 1272w, https://substackcdn.com/image/fetch/$s_!NK-U!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f6bd9e3-0975-4627-bd44-6e1c003bfa62_1596x1514.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NK-U!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f6bd9e3-0975-4627-bd44-6e1c003bfa62_1596x1514.png" width="606" height="574.7843406593406" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1f6bd9e3-0975-4627-bd44-6e1c003bfa62_1596x1514.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1381,&quot;width&quot;:1456,&quot;resizeWidth&quot;:606,&quot;bytes&quot;:291675,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!NK-U!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f6bd9e3-0975-4627-bd44-6e1c003bfa62_1596x1514.png 424w, https://substackcdn.com/image/fetch/$s_!NK-U!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f6bd9e3-0975-4627-bd44-6e1c003bfa62_1596x1514.png 848w, https://substackcdn.com/image/fetch/$s_!NK-U!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f6bd9e3-0975-4627-bd44-6e1c003bfa62_1596x1514.png 1272w, https://substackcdn.com/image/fetch/$s_!NK-U!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f6bd9e3-0975-4627-bd44-6e1c003bfa62_1596x1514.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>Costs</h3><p>DynamoDB Streams does not cost anything to enable. DynamoDB charges <strong>on the number of read requests </strong>made towards the table&#8217;s DynamoDB Stream. Each read request in terms of the stream is in the form of a <code>GetRecords</code> API call that can return up to 1000 records or 1 MB worth of records in the response, whichever is reached first. None of the <a href="https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Operations_Amazon_DynamoDB_Streams.html">other DynamoDB Stream APIs</a> (<a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/CostOptimization_StreamsUsage.html">source</a>) For DynamoDB Streams the cost is <strong>$0.25 per million reads.</strong></p><h3><strong>Approaches to Reading from Streams</strong></h3><p>DynamoDB streams can be processed in multiple ways. The most common approaches (<a href="https://aws.amazon.com/blogs/database/dynamodb-streams-use-cases-and-design-patterns/">source</a>) are:</p><ul><li><p>trigger based via AWS Lambdas</p></li><li><p>polling based with a standalone application that uses the Kinesis Client Library with the DynamoDB Streams Kinesis Adapter</p></li><li><p>polling based with a standalone application connecting directly to the Dynamo Stream APIs through the AWS SDK</p></li></ul><p><strong>The AWS Lambdas Approach</strong></p><p>Amazon DynamoDB comes integrated with AWS Lambda so that you can create <em><strong>triggers</strong></em>&#8212;pieces of code that automatically respond to events in DynamoDB Streams. Lambdas will poll the DynamoDB stream and, when they detect a new record, invoke your Lambda function and pass in one or more events.</p><p>Under the hood though, the AWS Lambda service will poll the stream for new records four times per second. (<a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Streams.Lambda.html">source</a>) The polling interval cannot be changed, you can only change things like the <em>batch size</em> or the <em>parallelization factor</em>. (<a href="https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-dynamodb.html">source</a>)</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bGST!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01c335ce-0171-4d6a-9f0b-3ce6ad7d0848_4096x1382.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bGST!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01c335ce-0171-4d6a-9f0b-3ce6ad7d0848_4096x1382.jpeg 424w, https://substackcdn.com/image/fetch/$s_!bGST!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01c335ce-0171-4d6a-9f0b-3ce6ad7d0848_4096x1382.jpeg 848w, https://substackcdn.com/image/fetch/$s_!bGST!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01c335ce-0171-4d6a-9f0b-3ce6ad7d0848_4096x1382.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!bGST!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01c335ce-0171-4d6a-9f0b-3ce6ad7d0848_4096x1382.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bGST!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01c335ce-0171-4d6a-9f0b-3ce6ad7d0848_4096x1382.jpeg" width="1456" height="491" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/01c335ce-0171-4d6a-9f0b-3ce6ad7d0848_4096x1382.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:491,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:192091,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!bGST!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01c335ce-0171-4d6a-9f0b-3ce6ad7d0848_4096x1382.jpeg 424w, https://substackcdn.com/image/fetch/$s_!bGST!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01c335ce-0171-4d6a-9f0b-3ce6ad7d0848_4096x1382.jpeg 848w, https://substackcdn.com/image/fetch/$s_!bGST!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01c335ce-0171-4d6a-9f0b-3ce6ad7d0848_4096x1382.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!bGST!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01c335ce-0171-4d6a-9f0b-3ce6ad7d0848_4096x1382.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Reading DynamoDB Streams using Lambda functions</figcaption></figure></div><p>Going with this approach would have a couple of advantages. The polling logic for data streams is automatically managed by Lambda functions, removing the need for manual implementation. Lambda functions provide built-in autoscaling capabilities, handling varying workloads efficiently without manual intervention. When using Lambda functions, you avoid the costs associated with making GetRecords calls to the streams, as this is handled by the AWS infrastructure.</p><p>On the other hand, there are significant additional costs involved, with an estimated expense of approximately $194 per month when handling 100 tables. The setup process requires extra effort, introducing changes to the deployment topology and adding complexity when establishing new data pipelines. Observability is limited as CloudWatch is the only available tool for monitoring and understanding what occurs within Lambda functions. Lambda functions must be designed to execute quickly, with minimal processing time, making them unsuitable for complex or long-running operations within the function logic.</p><p><strong>Using the DynamoDB Streams Kinesis Adapter</strong></p><p>The Amazon Kinesis Adapter is Amazon's recommended solution for consuming DynamoDB streams. However, a significant limitation is that this adapter is exclusively available in Java, making it unsuitable for non-Java applications. The Kinesis Client Library (KCL) offers a higher level of abstraction above the basic Kinesis Data Streams API, making the development process more straightforward and efficient. It provides robust batch processing capabilities, enabling efficient handling of multiple records simultaneously. The library includes automatic checkpointing functionality, maintaining accurate records of which data has been processed without requiring manual tracking.</p><p>The most significant limitation is that the DynamoDB Streams Kinesis Adapter is only implemented in Java and available through the awslabs/dynamodb-streams-kinesis-adapter repository, making it inaccessible for applications written in other programming languages.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0TuM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F065f2df7-bf4f-4ab2-922a-653c8e9412fe_1550x1380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0TuM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F065f2df7-bf4f-4ab2-922a-653c8e9412fe_1550x1380.png 424w, https://substackcdn.com/image/fetch/$s_!0TuM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F065f2df7-bf4f-4ab2-922a-653c8e9412fe_1550x1380.png 848w, https://substackcdn.com/image/fetch/$s_!0TuM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F065f2df7-bf4f-4ab2-922a-653c8e9412fe_1550x1380.png 1272w, https://substackcdn.com/image/fetch/$s_!0TuM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F065f2df7-bf4f-4ab2-922a-653c8e9412fe_1550x1380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0TuM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F065f2df7-bf4f-4ab2-922a-653c8e9412fe_1550x1380.png" width="534" height="475.31868131868134" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/065f2df7-bf4f-4ab2-922a-653c8e9412fe_1550x1380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1296,&quot;width&quot;:1456,&quot;resizeWidth&quot;:534,&quot;bytes&quot;:225159,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!0TuM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F065f2df7-bf4f-4ab2-922a-653c8e9412fe_1550x1380.png 424w, https://substackcdn.com/image/fetch/$s_!0TuM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F065f2df7-bf4f-4ab2-922a-653c8e9412fe_1550x1380.png 848w, https://substackcdn.com/image/fetch/$s_!0TuM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F065f2df7-bf4f-4ab2-922a-653c8e9412fe_1550x1380.png 1272w, https://substackcdn.com/image/fetch/$s_!0TuM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F065f2df7-bf4f-4ab2-922a-653c8e9412fe_1550x1380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Directly through the Dynamo Streams APIs using the AWS SDK</strong></p><p>The third option is to have a service that constantly polls the streams for new records using the available aws sdk for go. This has a couple of implications, we need to keep track of an index to know which records have been processed so far and due to the replicated nature of our systems, we need an idempotent way to achieve this.</p><p>And some things worth considering:</p><ul><li><p>Streams have rate limits - the <em>DescribeStream </em>endpoint can be called at a maximum rate of 10 times per second; the <em>GetRecords </em>endpoint can be be called at 5 TPS per stream shard or 2MB/s, whichever comes first (<a href="https://github.com/aws/aws-sdk-java-v2/issues/470">source</a>). Therefore, we cannot read more than 10 streams per sec.</p></li><li><p>You cannot have more than one active stream per table.</p></li><li><p>DynamoDB streams guarantee <strong>no duplicates </strong>and<strong> ordering of records</strong>.</p></li></ul><h3>Implemented Solution </h3><p>Most of the time reinventing the wheel is the worst solution you can choose. But what do you do when the current company policies and/or ecosystem makes it hard to integrate these libraries or this new set up in particular? Do you use the existing wheel but build a completely special car to work with it, or build a new wheel that fits into your existing car? All of the sudden, crafting this new wheel sounds like the easiest option. So here we are, reinventing the wheel because&#8230;it looked easy enough.</p><h3>Polling Processing Logic</h3><p>Before going into the high-level overview on how we&#8217;re using the aws go sdk to continuously poll the Dynamo Streams APIs, a couple of key concepts on how DynamoDB Streams work (which took us quite a lot of searching, digging and calls with AWS Support):</p><ul><li><p>We can have 2 types of shards: <strong>OPEN</strong> and <strong>CLOSED.</strong> </p></li><li><p>There is a one to one mapping between the dynamodb table partition and an open shard.</p></li><li><p>A shard is <strong>OPEN</strong> if <em><strong>EndingSequenceNumber == nil </strong></em>and <strong>CLOSED</strong> otherwise.</p></li><li><p>A shard can have (a lot of) successor shards (but every shard can only 1 child)</p><ul><li><p>for <strong>CLOSED</strong> shards, you can iterate through all its successors until you get to the end denoted by <em><strong>NextShardIterator == nil.</strong></em></p></li><li><p>for <strong>OPEN</strong> shards, <em><strong>NextShardIterator </strong></em>is never<em><strong> nil.</strong></em></p></li></ul></li><li><p>Every shard (parent or child) can contain records and the <em><strong>SequenceNo</strong></em> is a pointer to that shard record.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WajZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee2280d7-9812-4d37-9e67-769dbd06f5ae_6395x3009.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WajZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee2280d7-9812-4d37-9e67-769dbd06f5ae_6395x3009.png 424w, https://substackcdn.com/image/fetch/$s_!WajZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee2280d7-9812-4d37-9e67-769dbd06f5ae_6395x3009.png 848w, https://substackcdn.com/image/fetch/$s_!WajZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee2280d7-9812-4d37-9e67-769dbd06f5ae_6395x3009.png 1272w, https://substackcdn.com/image/fetch/$s_!WajZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee2280d7-9812-4d37-9e67-769dbd06f5ae_6395x3009.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WajZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee2280d7-9812-4d37-9e67-769dbd06f5ae_6395x3009.png" width="6395" height="3009" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ee2280d7-9812-4d37-9e67-769dbd06f5ae_6395x3009.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:3009,&quot;width&quot;:6395,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1083982,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!WajZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee2280d7-9812-4d37-9e67-769dbd06f5ae_6395x3009.png 424w, https://substackcdn.com/image/fetch/$s_!WajZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee2280d7-9812-4d37-9e67-769dbd06f5ae_6395x3009.png 848w, https://substackcdn.com/image/fetch/$s_!WajZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee2280d7-9812-4d37-9e67-769dbd06f5ae_6395x3009.png 1272w, https://substackcdn.com/image/fetch/$s_!WajZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fee2280d7-9812-4d37-9e67-769dbd06f5ae_6395x3009.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Overview of the main processing logic</figcaption></figure></div><p>We will store some shard/record information to be able to keep track of where we left off: </p><ul><li><p>a <em><strong>streams</strong></em> table - containing the <em><strong>table_name</strong></em> (which is the dynamodb table name we&#8217;re going to audit log), <em><strong>is_enabled</strong></em> (whether the dynamodb streams are currently enabled for it) and <em><strong>stream_arn</strong></em> (which is dynamodb stream identifier for the stream) </p></li><li><p>a <em><strong>streams_shards</strong></em> table - containing the <em><strong>stream_arn</strong></em>, <em><strong>shard_id </strong></em>(the identifier of the stream shard), <em><strong>sequence_no</strong></em> (the sequence number of the given shard which we will use to know when in the shard we left off processing, similar to how an index works) and <em><strong>status</strong></em> (which for us can be <em><strong>open</strong></em> meaning the shard is still open on dynamodb side, <em><strong>closed</strong></em> meaning the shard is closed on dynamodb shard but we still have records left to process and <em><strong>closedAndProcessed</strong></em> meaning the shard is closed on dynamodb side and we have processed all records)</p></li></ul><p>The way our processing logic will work is that given a stream_arn: </p><ul><li><p>we get a list of all the parent shards with their dynamodb statuses.</p></li><li><p>if it's dynamodb CLOSED:</p><ul><li><p>we check if we have already processed all records in it (where our status is <em><strong>closedAndProcessed</strong></em>) and if so skip</p></li><li><p>otherwise (where our status=closed) loop through all the successor shards until NextShardIterator == nil, process all the records in them and update shard status to <em><strong>closedAndProcessed</strong></em>. </p></li></ul></li><li><p>if OPEN:</p><ul><li><p>loop through the shards using NextShardIterator. </p></li></ul></li></ul><p>Our main issue is what do we do with open shards, since NextShardIterator is never nil? When do we know when to stop? At first, we made the assumption that if we get to a couple of consecutive shards with 0 length records, we can assume the shard is caught up. Unfortunately, this is not the case (confirmed with AWS Support team). Even if we encounter multiple consecutive shards with 0 records, it's generally recommended to continue iterating through subsequent shards, as we can have data in later shards. Now you would say, that&#8217;s not a big deal, just continuously loop and if you see new records, save those. To point out, you might not need extra logic here for making sure you&#8217;re not processing duplicate records, remember we&#8217;re always storing the map of shard_id with sequence_no. So when you&#8217;re processing a shard that&#8217;s already been seen, we&#8217;re going to start from the given sequence_no. </p><p>The problem with this approach is that we don&#8217;t have just a couple of dozens of successor shards for open shards, we proved to have a couple of thousands. A couple of thousands with zero records in them. This is for a table with quite a reasonable (not very high) throughput. Overall, this overcomplicates our approach quite a bit as the time it takes to complete doing a full read looking for new changes increased significantly. </p><p>How is dynamodb streams spinning successor shards so chaotically? Why do we have so many with zero records in them? Why aren&#8217;t records written sequentially, why do we have large &#8220;gaps&#8221; (zero length record shards) in between shards with data? Would love to get an answer to those questions. We ended up not getting one so far.</p><h3>Lessons Learnt</h3><p>Even though every project starts with an MVP to prove the feasibility of the solution, as it started in this case, it might be worth to do a test on a production scale environment. If we would have faked production workload on local/staging to test the MVP, maybe we would have noticed some of the issues and started asking questions at an earlier stage.</p><p></p>]]></content:encoded></item><item><title><![CDATA[Decentralised Social Media Explained: Inside Bluesky's Federated Architecture]]></title><description><![CDATA[On what makes a system decentralised and federated, Bluesky's current architecture and AT Protocol]]></description><link>https://blog.diana-enache.com/p/decentralised-social-media-explained</link><guid isPermaLink="false">https://blog.diana-enache.com/p/decentralised-social-media-explained</guid><dc:creator><![CDATA[Diana Darie]]></dc:creator><pubDate>Fri, 13 Dec 2024 15:42:25 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2d747b79-df0f-468a-a0f7-1ca326adcd0d_2901x1547.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This article is part of <em><strong>&#8220;Under the Hood&#8221;</strong></em>, a fairly new article series where I aim to deep dive into how real world systems work. Checkout the latest ones in this series: <em><strong><a href="https://blog.theengineeringcompass.com/p/from-pixels-to-information-a-comprehensive">From Pixels to Information: A Comprehensive Guide on QR Codes</a></strong></em> and <em><strong><a href="https://blog.theengineeringcompass.com/p/advanced-data-structures-for-discrete">How to Cron: Advanced Data Structures for Discrete Event Simulation</a>. </strong></em></p><div><hr></div><p>This time, we&#8217;ll have a look at how Bluesky is setup and go through the novel approaches they use to solve certain challenges. As of December 2025, Bluesky has crossed the 20 million users mark while being maintained by no more than 15 engineers. Martin Kleppman, author of the &#8220;Designing Data Intensive Applications&#8221;, currently a technical advisor, published a paper<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a> outlining how Bluesky is functioning as a federated and decentralised social media platform. Gergely Orosz's has two good articles covering the company&#8217;s early days, culture and evolutionary architecture if you would like to check them out.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a> In the meantime, let&#8217;s start with the basics.</p><h2>Centralised, decentralised and federated</h2><p><strong>Decentralised networks</strong> have no central authority or server, and all participants (nodes) are equal and have the same capabilities. Data and control are distributed across all nodes. If one node fails, the network continues to function. One example of a fully decentralised network is Bitcoin - no single entity controls it, and all participants maintain a copy of the ledger.</p><p><strong>Federated networks</strong> have multiple independent servers that can communicate with each other, where each server has its own administrator and user base. Users on different servers can interact with each other. Each server follows its own rules while adhering to a common protocol. For example, email providers (gmail, yahoo, and other providers) run their own servers but can communicate with each other via standard protocols.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!QnhJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64f1de28-b5a6-4ec1-944a-36ea880c0a47_1316x388.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QnhJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64f1de28-b5a6-4ec1-944a-36ea880c0a47_1316x388.png 424w, https://substackcdn.com/image/fetch/$s_!QnhJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64f1de28-b5a6-4ec1-944a-36ea880c0a47_1316x388.png 848w, https://substackcdn.com/image/fetch/$s_!QnhJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64f1de28-b5a6-4ec1-944a-36ea880c0a47_1316x388.png 1272w, https://substackcdn.com/image/fetch/$s_!QnhJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64f1de28-b5a6-4ec1-944a-36ea880c0a47_1316x388.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QnhJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64f1de28-b5a6-4ec1-944a-36ea880c0a47_1316x388.png" width="578" height="170.41337386018236" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/64f1de28-b5a6-4ec1-944a-36ea880c0a47_1316x388.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:388,&quot;width&quot;:1316,&quot;resizeWidth&quot;:578,&quot;bytes&quot;:43931,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!QnhJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64f1de28-b5a6-4ec1-944a-36ea880c0a47_1316x388.png 424w, https://substackcdn.com/image/fetch/$s_!QnhJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64f1de28-b5a6-4ec1-944a-36ea880c0a47_1316x388.png 848w, https://substackcdn.com/image/fetch/$s_!QnhJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64f1de28-b5a6-4ec1-944a-36ea880c0a47_1316x388.png 1272w, https://substackcdn.com/image/fetch/$s_!QnhJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64f1de28-b5a6-4ec1-944a-36ea880c0a47_1316x388.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><figcaption class="image-caption">Comparison between the three types of networks: centralised, decentralised and federated. Red nodes represent servers or hubs. Green nodes represent users. Solid lines show direct connections. Dashed lines show federation between servers.</figcaption></figure></div><p>A system can be both federated and decentralised. This is often called a <strong>federated decentralised network</strong>. The federation part provides standard protocols for communication, interoperability between different servers/instances and local administration and rules. The decentralisation part ensures no central authority controls the entire network, anyone can set up their own server/instance and there is no single point of failure.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ggB3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febec0bc4-d77a-495b-8793-5a9844a4a104_1286x1062.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ggB3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febec0bc4-d77a-495b-8793-5a9844a4a104_1286x1062.png 424w, https://substackcdn.com/image/fetch/$s_!ggB3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febec0bc4-d77a-495b-8793-5a9844a4a104_1286x1062.png 848w, https://substackcdn.com/image/fetch/$s_!ggB3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febec0bc4-d77a-495b-8793-5a9844a4a104_1286x1062.png 1272w, https://substackcdn.com/image/fetch/$s_!ggB3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febec0bc4-d77a-495b-8793-5a9844a4a104_1286x1062.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ggB3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febec0bc4-d77a-495b-8793-5a9844a4a104_1286x1062.png" width="310" height="256.0031104199067" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ebec0bc4-d77a-495b-8793-5a9844a4a104_1286x1062.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1062,&quot;width&quot;:1286,&quot;resizeWidth&quot;:310,&quot;bytes&quot;:96682,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ggB3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febec0bc4-d77a-495b-8793-5a9844a4a104_1286x1062.png 424w, https://substackcdn.com/image/fetch/$s_!ggB3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febec0bc4-d77a-495b-8793-5a9844a4a104_1286x1062.png 848w, https://substackcdn.com/image/fetch/$s_!ggB3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febec0bc4-d77a-495b-8793-5a9844a4a104_1286x1062.png 1272w, https://substackcdn.com/image/fetch/$s_!ggB3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febec0bc4-d77a-495b-8793-5a9844a4a104_1286x1062.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Example of how a federated decentralised network would look like. Each cluster represents a federation of servers. Each federation has multiple servers (red nodes). Users (green nodes) are connected to different servers. Solid lines show direct connections within federations. Dashed lines aka standard protocols show federation connections between groups.</figcaption></figure></div><h2>In which category should X/Mastodon be part of?</h2><p>X maintains complete centralised control over its platform. They have exclusive authority over your personal data, your identity, and content management (which includes both moderation policies and feed generation). While X has taken steps toward transparency by partially open-sourcing their algorithm<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a>, users remain largely passive observers - able to understand parts of how the system works but with minimal ability to influence or modify its operation.</p><p>Mastodon is federated because different servers can communicate with each other using the ActivityPub protocol. It's partially decentralised because no one owns or controls the entire network and anyone can set up their own Mastodon server. If one server goes down, the rest of the network continues functioning. The key difference from purely decentralised systems (like Bitcoin) is that these networks maintain some organisational structure through federation while still preventing central control. They strike a balance between complete decentralisation and practical usability. One disadvantage though, is that in the same way there are huge email providers, there are big Mastodon servers. Your user identity becomes tied to a server and it might get challenging (if not impossible) to move to another server. </p><h2>Bluesky architecture high-level overview</h2><p>Bluesky uses a protocol called the <strong>AT Protocol (Authenticated Transfer Protocol)</strong><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a> aka <strong>atproto</strong>, which works similar to email in some ways. Just like how email allows you to use Gmail but still message someone with a Yahoo account, Bluesky lets you choose different providers (called<strong> Personal Data Servers </strong>or<strong> PDS</strong>) to host your account, communicate with users on different servers, and take your account and data with you if you want to switch providers. </p><p>The key aspects through which Bluesky <em>encourages</em> decentralisation is that anyone can run their own server and connect to the network, users have data portability (can move their account between providers) and the protocol is open, meaning anyone can build compatible apps or services.</p><p>Let&#8217;s go through the main components that make the Bluesky&#8217;s architecture.</p><p>We have the <strong>PDS (Personal Data Server)</strong> which is the central part of the architecture. It hosts user repositories and data, manages user identity, orchestrates requests to other services, handles data sync and federation, can be self-hosted or provided (like Bluesky PDS). <strong>User Data Repository</strong> holds the <strong>User Identity (DID)</strong>, which is the decentralised identifier for authentication. It handles the cryptographic authentication, signing and verification and holds the records structure like posts, follows, likes and profile data. In order to consume data, aggregate it to your liking and distribute it in real time, you have the <strong>Network Relays</strong> which index and collect content from PDSs and then use <strong>Firehose</strong> to distribute it so that you can process updates in real time. The firehose data is consumed by the <strong>Feed Generator</strong> (<strong>Discover</strong>) to create custom content feeds and by the <strong>Labeling Service</strong> (<strong>Ozone</strong>) to provide content moderation, tagging and content classification. The data from those two Opinionated Services is consumed by the App Views, which acts as the user-facing platform.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!otZi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5a61cc1-7392-4ca9-b0b3-b42ea5fb3779_2948x1564.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!otZi!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5a61cc1-7392-4ca9-b0b3-b42ea5fb3779_2948x1564.png 424w, https://substackcdn.com/image/fetch/$s_!otZi!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5a61cc1-7392-4ca9-b0b3-b42ea5fb3779_2948x1564.png 848w, https://substackcdn.com/image/fetch/$s_!otZi!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5a61cc1-7392-4ca9-b0b3-b42ea5fb3779_2948x1564.png 1272w, https://substackcdn.com/image/fetch/$s_!otZi!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5a61cc1-7392-4ca9-b0b3-b42ea5fb3779_2948x1564.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!otZi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5a61cc1-7392-4ca9-b0b3-b42ea5fb3779_2948x1564.png" width="2948" height="1564" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d5a61cc1-7392-4ca9-b0b3-b42ea5fb3779_2948x1564.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1564,&quot;width&quot;:2948,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:296646,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!otZi!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5a61cc1-7392-4ca9-b0b3-b42ea5fb3779_2948x1564.png 424w, https://substackcdn.com/image/fetch/$s_!otZi!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5a61cc1-7392-4ca9-b0b3-b42ea5fb3779_2948x1564.png 848w, https://substackcdn.com/image/fetch/$s_!otZi!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5a61cc1-7392-4ca9-b0b3-b42ea5fb3779_2948x1564.png 1272w, https://substackcdn.com/image/fetch/$s_!otZi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5a61cc1-7392-4ca9-b0b3-b42ea5fb3779_2948x1564.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">High level overview of Bluesky&#8217;s architecture</figcaption></figure></div><h2>Interoperation and federability</h2><p>The protocol uses a system called <strong>"Lexicons"</strong>, these are like agreed-upon vocabularies that define how different types of data (posts, likes, follows, etc.) should be structured. This standardization allows different servers and clients to understand each other, similar to how different email clients all understand what an email header should look like.</p><p>Each server supports specific features by implementing "lexicons" - there are core ones (starting with <code>com.atproto.*</code>) that handle basic stuff like syncing user data, and social-focused ones (starting with <code>app.bsky.*</code>) that enable social media features.</p><p>Unlike the regular web, which shares HTML pages that determine both content and appearance, the AT Protocol only shares the underlying data in a structured format. This means apps can display the same information in their own unique ways, without needing to download and run someone else's display code (HTML/JS/CSS). It's like getting pure information that each app can then present however it wants. <a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dioQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89063c15-62ff-401f-8d6b-853373b38e4c_1652x735.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dioQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89063c15-62ff-401f-8d6b-853373b38e4c_1652x735.png 424w, https://substackcdn.com/image/fetch/$s_!dioQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89063c15-62ff-401f-8d6b-853373b38e4c_1652x735.png 848w, https://substackcdn.com/image/fetch/$s_!dioQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89063c15-62ff-401f-8d6b-853373b38e4c_1652x735.png 1272w, https://substackcdn.com/image/fetch/$s_!dioQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89063c15-62ff-401f-8d6b-853373b38e4c_1652x735.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dioQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89063c15-62ff-401f-8d6b-853373b38e4c_1652x735.png" width="1652" height="735" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/89063c15-62ff-401f-8d6b-853373b38e4c_1652x735.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:735,&quot;width&quot;:1652,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:78526,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!dioQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89063c15-62ff-401f-8d6b-853373b38e4c_1652x735.png 424w, https://substackcdn.com/image/fetch/$s_!dioQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89063c15-62ff-401f-8d6b-853373b38e4c_1652x735.png 848w, https://substackcdn.com/image/fetch/$s_!dioQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89063c15-62ff-401f-8d6b-853373b38e4c_1652x735.png 1272w, https://substackcdn.com/image/fetch/$s_!dioQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89063c15-62ff-401f-8d6b-853373b38e4c_1652x735.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>The user data repository</h2><p>A noteworthy feature is <strong>repositories</strong> ("<strong>repos</strong>"). Each user has their own personal repository that contains all their data - posts, follows, likes, etc. These repos are designed to be efficiently synced between servers, maintain a verifiable history of changes and allow users to take their entire social presence with them if they switch providers. </p><p>The AT Protocol (ATP) has some interesting technical characteristics that enable decentralisation. The core of ATP is built around something called <strong>"Self-Authenticating Data Structures"</strong>. Every post, profile, and interaction is signed cryptographically, which means data can be verified as authentic regardless of which server it comes from, users truly own their identity through cryptographic keys and content can't be tampered with without detection.</p><p>An interesting technical choice is that ATP uses <strong>DIDs (Decentralised Identifiers)</strong> as the foundation for user identity, which are persistent identifiers that remain valid even if you change providers. </p><p>Every user has two identifiers: </p><ul><li><p>A human-readable handle (like username.bsky.social or custom domain)</p></li><li><p>A permanent DID (Decentralised Identifier, like did:plc:xyz123...)</p></li></ul><pre><code>User Handle (e.g., alice.bsky.social)
       &#8595;
Resolves to DID (did:plc:xyz123...)
       &#8595;
DID looks up in PLC server
       &#8595;
Returns DID Document containing:
- Public key
- PDS server location
- Handle verification</code></pre><p>Users can change their handle without losing their identity because the DID remains constant. The DID document points back to your handle, creating a verification loop. Any changes to the DID document must be signed with your private key and create a verifiable chain of updates. All updates require cryptographic signatures. Changes create a verifiable chain (like a "mini-blockchain"). Public data is self-verifiable. Third parties can detect manipulation. </p><p>Some limitations with the current approach are that it relies on centralised DNS system, there&#8217;s currently a single PLC server managed by Bluesky and most users' private keys are currently managed by Bluesky.</p><h2>How decentralised and federated is Bluesky actually? </h2><p>Bluesky doesn't use a traditional message-passing system like other federated networks (ActivityPub, XMPP, email). Instead, it uses a "shared heap" architecture where data exists in one global pool. There's no direct message-passing between hosts, which is a common federation pattern. Most users are currently hosted on Bluesky's PDS (Personal Data Server) instances. The chat/DMs service is completely centralised and most services rely on Bluesky's relay as a firehose.</p><p>The platform is not yet fully decentralised as the power is not evenly diffused throughout the system, most users run the Bluesky app, most developers work with Bluesky-defined application schemas (Lexicons), most self-hosted users run Bluesky's PDS software. Running a full-network relay requires significant resources (16TB of fast NVMe disk). Most DID PLC accounts don't have independently controlled PLC rotation keys configured.</p><blockquote><p><em>One thing I would not debate is that much of the protocol and the network is reliant on Bluesky in material terms today. Almost everybody in the atproto network is hosted on a Bluesky PDS instance. Most self-hosted folks run the Bluesky PDS software. Most services use a Bluesky relay as a firehose. Most users run the Bluesky app. Most developers are working with the Bluesky-defined application schemas (Lexicons). - Bryan Newbold, Protocol Engineer at Bluesky </em><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-6" href="#footnote-6" target="_self">6</a></p></blockquote><p>While Bluesky's underlying protocol (atproto) <strong>is designed to support decentralisation</strong>, in practice most of the network currently runs through Bluesky the company. Almost everyone uses Bluesky's servers, app, and relay services - making it functionally similar to Twitter/X today. The key difference is in the architecture.</p><p>It allows for <em>"credible exit"</em>, users can leave without losing their data or connections. It Supports independent Lexicons (like the whtwnd.com blogging platform). Every major infrastructure component can be substituted without friction. Users can self-host their own instances. Lets users own their identity and data. The protocol is designed to prevent any single party from moderating the entire network.</p><p>So, unlike Twitter, Bluesky's infrastructure is built to allow users and developers to run their own independent services, migrate their data, and participate in the network without relying on Bluesky's systems. This capability exists even though relatively few are using it right now.</p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p><a href="https://arxiv.org/pdf/2402.03239">Bluesky and the AT Protocol: Usable Decentralised Social Media</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p><a href="https://newsletter.pragmaticengineer.com/p/bluesky">Building Bluesky: a Distributed Social Network (Real-World Engineering Challenges)</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p><a href="https://github.com/twitter/the-algorithm">X&#8217;s Recommendation Algorithm</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-4" href="#footnote-anchor-4" class="footnote-number" contenteditable="false" target="_self">4</a><div class="footnote-content"><p><a href="https://atproto.com/">AT Protocol Documentation</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-5" href="#footnote-anchor-5" class="footnote-number" contenteditable="false" target="_self">5</a><div class="footnote-content"><p><a href="https://atproto.com/guides/overview#interoperation">AT Protocol Interoperation Overview Guide</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-6" href="#footnote-anchor-6" class="footnote-number" contenteditable="false" target="_self">6</a><div class="footnote-content"><p><a href="https://whtwnd.com/bnewbold.net/3lbvbtqrg5t2t">Bryan Newbold&#8217;s Reply on Bluesky and Decentralisation</a></p></div></div>]]></content:encoded></item><item><title><![CDATA[How to Cron: Advanced Data Structures for Discrete Event Simulation]]></title><description><![CDATA[On algorithmic improvements in the event set management, from O(&#8730;n) to O(1).]]></description><link>https://blog.diana-enache.com/p/advanced-data-structures-for-discrete</link><guid isPermaLink="false">https://blog.diana-enache.com/p/advanced-data-structures-for-discrete</guid><dc:creator><![CDATA[Diana Darie]]></dc:creator><pubDate>Mon, 09 Dec 2024 16:49:41 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/a94c23c0-15b8-453f-b19b-2fefcecfb027_2376x1388.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Recently, I was working on a service whose main responsibility was to schedule tasks and trigger their run at regular intervals. As with all projects, I check to see what's out there and if there are solutions that have been proved better and more efficient than what I already had in mind. So, I started looking into how the unix cron is doing its scheduling and stumbled upon a couple of interesting data structures that I wanted to take a deep dive into. Here's what I hope is a successful summary.</p><h2>The early cron days</h2><p>The original cron was designed by Ken Thompson in Unix V7 (around 1979) and was later rewritten by Dennis Ritchie. It used to work in a simple way. It would read the crontab files from <code>/usr/lib/crontab</code>, used a simple in memory table for job scheduling and had one main process that woke up every minute and determine if any commands must run at the current date and time, and if so, run them as the superuser, root.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0s7G!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffadc2c66-ac94-425c-ab0e-8ab47d96adb1_2683x873.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0s7G!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffadc2c66-ac94-425c-ab0e-8ab47d96adb1_2683x873.png 424w, https://substackcdn.com/image/fetch/$s_!0s7G!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffadc2c66-ac94-425c-ab0e-8ab47d96adb1_2683x873.png 848w, https://substackcdn.com/image/fetch/$s_!0s7G!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffadc2c66-ac94-425c-ab0e-8ab47d96adb1_2683x873.png 1272w, https://substackcdn.com/image/fetch/$s_!0s7G!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffadc2c66-ac94-425c-ab0e-8ab47d96adb1_2683x873.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0s7G!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffadc2c66-ac94-425c-ab0e-8ab47d96adb1_2683x873.png" width="2683" height="873" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fadc2c66-ac94-425c-ab0e-8ab47d96adb1_2683x873.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:873,&quot;width&quot;:2683,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:106976,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!0s7G!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffadc2c66-ac94-425c-ab0e-8ab47d96adb1_2683x873.png 424w, https://substackcdn.com/image/fetch/$s_!0s7G!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffadc2c66-ac94-425c-ab0e-8ab47d96adb1_2683x873.png 848w, https://substackcdn.com/image/fetch/$s_!0s7G!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffadc2c66-ac94-425c-ab0e-8ab47d96adb1_2683x873.png 1272w, https://substackcdn.com/image/fetch/$s_!0s7G!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffadc2c66-ac94-425c-ab0e-8ab47d96adb1_2683x873.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">Unix V7 Cron Scheduling</figcaption></figure></div><p>This method presented a couple of challenges. It could easily overload the system if too many jobs ran simultaneously. It consumed resources every minute whether there was a job to be run or not. Performance degraded with more entries. It wasn&#8217;t suitable for large systems with many users. Memory usage grew linearly with number of jobs. There was no way to limit the number of jobs per user.</p><p>These limitations led to the development of more sophisticated cron implementations for multi-user capability.</p><h2>The Franta-Maly Event List Approach</h2><p>The Unix System V came with an upgraded version of cron based on the 1977 paper by W.R. Franta and Kurt Maly, <em>An Efficient Data Structure for the Simulation Event Set</em>. [1] In this paper, they presented a new event scheduling algorithm that improves on previously published algorithms. Robert Brown, a Purdue graduate student, noticed similarities between cron and discrete event simulators, leading him to implement the Franta-Maly event list manager. In 1979, Keith Williamson, a new graduate student, developed Brown's prototype into a production-ready multi-user cron service at Purdue.</p><p>The cron algorithm begins by searching for <code>.crontab</code> files in all users' home directories at startup. For each discovered crontab file, it calculates the next future execution time for each command and adds these commands to the Franta-Maly event list, along with their execution times and five-field time specifiers. The main loop then continuously examines the first task in the queue, calculating its future execution time. The system sleeps until that time, then wakes to verify the time and execute the queued task in the background using the original user's privileges. After execution, it recalculates the next runtime for that command and reinserts it into the event list accordingly.</p><p>The daemon implements two monitoring mechanisms for crontab file changes: it processes SIGHUP signals to trigger immediate rescans of modified crontab files, and it maintains scheduled wake-up checks at 30-minute intervals (on the hour and half-hour) to detect any crontab modifications. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!oxEk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96caaefc-9565-4fe1-8478-72d1b5d597f5_5870x8819.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!oxEk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96caaefc-9565-4fe1-8478-72d1b5d597f5_5870x8819.png 424w, https://substackcdn.com/image/fetch/$s_!oxEk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96caaefc-9565-4fe1-8478-72d1b5d597f5_5870x8819.png 848w, https://substackcdn.com/image/fetch/$s_!oxEk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96caaefc-9565-4fe1-8478-72d1b5d597f5_5870x8819.png 1272w, https://substackcdn.com/image/fetch/$s_!oxEk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96caaefc-9565-4fe1-8478-72d1b5d597f5_5870x8819.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!oxEk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96caaefc-9565-4fe1-8478-72d1b5d597f5_5870x8819.png" width="5870" height="8819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/96caaefc-9565-4fe1-8478-72d1b5d597f5_5870x8819.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:8819,&quot;width&quot;:5870,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1932703,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!oxEk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96caaefc-9565-4fe1-8478-72d1b5d597f5_5870x8819.png 424w, https://substackcdn.com/image/fetch/$s_!oxEk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96caaefc-9565-4fe1-8478-72d1b5d597f5_5870x8819.png 848w, https://substackcdn.com/image/fetch/$s_!oxEk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96caaefc-9565-4fe1-8478-72d1b5d597f5_5870x8819.png 1272w, https://substackcdn.com/image/fetch/$s_!oxEk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F96caaefc-9565-4fe1-8478-72d1b5d597f5_5870x8819.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Unix System V Cron Scheduling based on the Franta-Maly event list</figcaption></figure></div><p>The Franta-Maly event list (Two-Level algorithm) has a time complexity of <strong>O(&#8730;n)</strong> in the worst case scenario, driven by its two-tier data structure design and event insertion mechanism.</p><h4>The Two-Level (TL) Algorithm Data Structure</h4><p>The Two-Level (TL) algorithm proposed by Franta and Maly utilises a sophisticated data structure to efficiently manage event notices in discrete event simulations. The primary goal of this structure is to reduce the number of comparisons required to find the correct position to insert a new event notice, thus optimising the simulation's performance. The algorithm utilises a data structure inspired by indexed lists and balanced tree concepts (3-2 trees), to minimise the computational cost of scheduling and processing events.</p><p>The data structure consists of 3 layers:</p><ul><li><p><strong>the index list layer</strong> - The TL algorithm uses an index list to divide the range of event times into a number of equal-sized intervals. Each element in the index list points to a "dummy key" which represents the boundary of an interval.</p></li><li><p><strong>the secondary key layer</strong> - The efficiency of the TL algorithm lies in the introduction of secondary keys within each interval. These keys, associated with the right boundary dummy key, point to sublists of event notices within the interval<strong>. </strong>This two-level indexing scheme enables more efficient searching and insertion operations.</p></li><li><p><strong>the event notices layer</strong> - Each interval is further divided into sublists, each headed by a secondary key. The sublists are designed to be balanced, meaning they don't grow excessively large. The maximum size of each sublist is controlled by <strong>nlim</strong> parameter.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-7im!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff52f4b66-7afc-40ba-b064-9aa99acc7235_4829x1595.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-7im!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff52f4b66-7afc-40ba-b064-9aa99acc7235_4829x1595.png 424w, https://substackcdn.com/image/fetch/$s_!-7im!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff52f4b66-7afc-40ba-b064-9aa99acc7235_4829x1595.png 848w, https://substackcdn.com/image/fetch/$s_!-7im!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff52f4b66-7afc-40ba-b064-9aa99acc7235_4829x1595.png 1272w, https://substackcdn.com/image/fetch/$s_!-7im!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff52f4b66-7afc-40ba-b064-9aa99acc7235_4829x1595.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-7im!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff52f4b66-7afc-40ba-b064-9aa99acc7235_4829x1595.png" width="4829" height="1595" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f52f4b66-7afc-40ba-b064-9aa99acc7235_4829x1595.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1595,&quot;width&quot;:4829,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:405897,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-7im!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff52f4b66-7afc-40ba-b064-9aa99acc7235_4829x1595.png 424w, https://substackcdn.com/image/fetch/$s_!-7im!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff52f4b66-7afc-40ba-b064-9aa99acc7235_4829x1595.png 848w, https://substackcdn.com/image/fetch/$s_!-7im!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff52f4b66-7afc-40ba-b064-9aa99acc7235_4829x1595.png 1272w, https://substackcdn.com/image/fetch/$s_!-7im!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff52f4b66-7afc-40ba-b064-9aa99acc7235_4829x1595.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Representation of the Two-Layer/ Franta Maly Event List</figcaption></figure></div><p><strong>The Insert Operation - Worst Case Complexity: O(&#8730;n)</strong></p><p>Let&#8217;s say we want to insert a new event with t=1.3. The Franta-Maly insertion process follows a systematic sequence through the data structure's layers. First, we calculate the target interval by applying the formula i = [(t - lowerbound)/dt] to determine the precise interval containing the event time, which leads us to the corresponding dummy key entry in the index list.</p><p>Next, we traverse the sequence of secondary keys associated with the identified dummy key until locating the appropriate insertion point. For an event with time t=1.3, this involves scanning until we find it belongs between secondary keys 1.2 and 1.5.</p><p>The actual insertion occurs by placing the event notice in its correct time-ordered position within the identified sublist. In our example, the new event with t=1.3 is inserted between existing events with times 1.2 and 1.4, maintaining the temporal ordering of the sublist.</p><p>Finally, we execute a balance check to maintain the data structure's efficiency. The system verifies if the insertion has caused the sublist to exceed its maximum size (nlim). When the size limit is exceeded, the structure triggers one of two rebalancing operations: either transferring the last notice to an adjacent list or creating a new secondary key. If the sublist remains within size constraints, the insertion completes without requiring rebalancing.</p><p>The worst case complexity occurs when all n notices are associated with the same dummy key and the new event being inserted has a time smaller than all other notices in the structure. The complexity is calculated as: <strong>cw(n) = n/nlim + nlim</strong>,<strong> </strong>where nlim is optimally set to &#8730;n to minimize the worst case complexity.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!rcUc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcacdc3c7-a00c-47d9-a795-6d016e3c3de0_5031x1826.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rcUc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcacdc3c7-a00c-47d9-a795-6d016e3c3de0_5031x1826.png 424w, https://substackcdn.com/image/fetch/$s_!rcUc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcacdc3c7-a00c-47d9-a795-6d016e3c3de0_5031x1826.png 848w, https://substackcdn.com/image/fetch/$s_!rcUc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcacdc3c7-a00c-47d9-a795-6d016e3c3de0_5031x1826.png 1272w, https://substackcdn.com/image/fetch/$s_!rcUc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcacdc3c7-a00c-47d9-a795-6d016e3c3de0_5031x1826.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!rcUc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcacdc3c7-a00c-47d9-a795-6d016e3c3de0_5031x1826.png" width="5031" height="1826" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cacdc3c7-a00c-47d9-a795-6d016e3c3de0_5031x1826.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1826,&quot;width&quot;:5031,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:532565,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!rcUc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcacdc3c7-a00c-47d9-a795-6d016e3c3de0_5031x1826.png 424w, https://substackcdn.com/image/fetch/$s_!rcUc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcacdc3c7-a00c-47d9-a795-6d016e3c3de0_5031x1826.png 848w, https://substackcdn.com/image/fetch/$s_!rcUc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcacdc3c7-a00c-47d9-a795-6d016e3c3de0_5031x1826.png 1272w, https://substackcdn.com/image/fetch/$s_!rcUc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcacdc3c7-a00c-47d9-a795-6d016e3c3de0_5031x1826.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Representation of how inserting a new event looks like</figcaption></figure></div><p><strong>The Search Operation -</strong> <strong>Worst Case Complexity: O(&#8730;n)</strong></p><p>Let&#8217;s say we want to search for an event with t=1.3.</p><p>The search process in the Franta-Maly structure executes in three sequential phases. The first phase calculates the target interval using the formula i = [(t - lowerbound)/dt], which maps directly to the corresponding dummy key in the index list. This initial lookup operates in constant time O(1).</p><p>The second phase traverses the secondary key sequence within the identified interval until locating the appropriate sublist. For a target time t=1.3, the algorithm scans between secondary keys 1.2 and 1.5, ultimately selecting SK2's sublist. This traversal has a worst-case complexity of O(&#8730;n).</p><p>The final phase executes a linear search within the selected sublist to find the exact match or appropriate position. Since the maximum sublist size is constrained by nlim (&#8730;n), this search also operates with worst-case complexity O(&#8730;n). The combination of these three phases yields an overall worst-case complexity of O(&#8730;n), though practical performance often approaches constant time.</p><h2>Calendar Queues (CQ)</h2><p>A calendar queue is a priority queue data structure specifically designed for efficient handling of time-based events. It was introduced by <em>Randy Brown in 1988 </em>[2] and is particularly useful in discrete event simulation systems. </p><p>The queue is organized like a calendar, divided into "buckets" (like days or time slots). Each bucket represents a fixed-width time interval. Events within each bucket are sorted by their timestamp. The buckets are arranged in a circular array (wrapping around like a year calendar)</p><p>The data structure consists of 4 components:</p><ul><li><p><strong>Buckets:</strong> An array representing days in a year, each element pointing to a sorted linked list of events scheduled for that day<strong>.</strong></p></li><li><p><strong>Event Nodes:</strong> Contain information about the event, including its time (priority) and any associated data. These are organised into sorted linked lists within each bucket.</p></li><li><p><strong>Circular Calendar:</strong> Events can be scheduled up to a year in advance. Once the last day of the year is reached, the calendar wraps around to the first day, allowing for continuous event scheduling without data structure manipulation<strong>2</strong>.</p></li><li><p><strong>Event Dates:</strong> Each event node stores its scheduled date to handle events scheduled beyond a year. Events with future dates are skipped during dequeue operations until the calendar reaches their scheduled year</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!p1wv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22747f86-0032-425d-a892-b0b03657293f_2240x936.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!p1wv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22747f86-0032-425d-a892-b0b03657293f_2240x936.png 424w, https://substackcdn.com/image/fetch/$s_!p1wv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22747f86-0032-425d-a892-b0b03657293f_2240x936.png 848w, https://substackcdn.com/image/fetch/$s_!p1wv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22747f86-0032-425d-a892-b0b03657293f_2240x936.png 1272w, https://substackcdn.com/image/fetch/$s_!p1wv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22747f86-0032-425d-a892-b0b03657293f_2240x936.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!p1wv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22747f86-0032-425d-a892-b0b03657293f_2240x936.png" width="1456" height="608" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/22747f86-0032-425d-a892-b0b03657293f_2240x936.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:608,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&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_!p1wv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22747f86-0032-425d-a892-b0b03657293f_2240x936.png 424w, https://substackcdn.com/image/fetch/$s_!p1wv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22747f86-0032-425d-a892-b0b03657293f_2240x936.png 848w, https://substackcdn.com/image/fetch/$s_!p1wv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22747f86-0032-425d-a892-b0b03657293f_2240x936.png 1272w, https://substackcdn.com/image/fetch/$s_!p1wv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22747f86-0032-425d-a892-b0b03657293f_2240x936.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Representation of Brown&#8217;s Calendar Queues</figcaption></figure></div><p>The above image shows how Brown&#8217;s Calendar Queue looks like, where the year starts at 12.0 and end at 16.0 and the bucket width is 0.5 time units. </p><h4><strong>How are events inserted?</strong></h4><p>Events are assigned to buckets using this formula:</p><pre><code>bucket_number = floor(priority/bucket_width) % number_of_buckets</code></pre><p>Let&#8217;s say we want to insert a new element 14.6 and we have the following initial state:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LcUa!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52cefb96-93ed-4018-bb53-c729cbcaf4cc_2328x552.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LcUa!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52cefb96-93ed-4018-bb53-c729cbcaf4cc_2328x552.png 424w, https://substackcdn.com/image/fetch/$s_!LcUa!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52cefb96-93ed-4018-bb53-c729cbcaf4cc_2328x552.png 848w, https://substackcdn.com/image/fetch/$s_!LcUa!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52cefb96-93ed-4018-bb53-c729cbcaf4cc_2328x552.png 1272w, https://substackcdn.com/image/fetch/$s_!LcUa!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52cefb96-93ed-4018-bb53-c729cbcaf4cc_2328x552.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LcUa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52cefb96-93ed-4018-bb53-c729cbcaf4cc_2328x552.png" width="1456" height="345" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/52cefb96-93ed-4018-bb53-c729cbcaf4cc_2328x552.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:345,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&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_!LcUa!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52cefb96-93ed-4018-bb53-c729cbcaf4cc_2328x552.png 424w, https://substackcdn.com/image/fetch/$s_!LcUa!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52cefb96-93ed-4018-bb53-c729cbcaf4cc_2328x552.png 848w, https://substackcdn.com/image/fetch/$s_!LcUa!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52cefb96-93ed-4018-bb53-c729cbcaf4cc_2328x552.png 1272w, https://substackcdn.com/image/fetch/$s_!LcUa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52cefb96-93ed-4018-bb53-c729cbcaf4cc_2328x552.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>We have the current year that starts at 12.0 and ends at 16.0 (range of 4.0 units), with a bucket width = 0.5 time units and 8 buckets. We calculate the </p><pre><code>bucket_number = floor(14.6/0.5)%8 = 29%8 = 5</code></pre><p>The element belongs to bucket 5 and will be inserted into sorted position into the bucket&#8217;s linked list.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!E9to!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F498f0a26-3f1d-4e30-bc43-c2568c346fc4_2476x552.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!E9to!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F498f0a26-3f1d-4e30-bc43-c2568c346fc4_2476x552.png 424w, https://substackcdn.com/image/fetch/$s_!E9to!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F498f0a26-3f1d-4e30-bc43-c2568c346fc4_2476x552.png 848w, https://substackcdn.com/image/fetch/$s_!E9to!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F498f0a26-3f1d-4e30-bc43-c2568c346fc4_2476x552.png 1272w, https://substackcdn.com/image/fetch/$s_!E9to!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F498f0a26-3f1d-4e30-bc43-c2568c346fc4_2476x552.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!E9to!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F498f0a26-3f1d-4e30-bc43-c2568c346fc4_2476x552.png" width="1456" height="325" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/498f0a26-3f1d-4e30-bc43-c2568c346fc4_2476x552.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:325,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&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_!E9to!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F498f0a26-3f1d-4e30-bc43-c2568c346fc4_2476x552.png 424w, https://substackcdn.com/image/fetch/$s_!E9to!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F498f0a26-3f1d-4e30-bc43-c2568c346fc4_2476x552.png 848w, https://substackcdn.com/image/fetch/$s_!E9to!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F498f0a26-3f1d-4e30-bc43-c2568c346fc4_2476x552.png 1272w, https://substackcdn.com/image/fetch/$s_!E9to!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F498f0a26-3f1d-4e30-bc43-c2568c346fc4_2476x552.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>This insertion process maintains <strong>O(1)</strong> average complexity since bucket calculation is <strong>O(1)</strong>, each bucket contains a small, roughly constant number of events, and searching within a bucket's linked list is therefore bounded by a constant.</p><h4><strong>How is bucket width calculated?</strong> </h4><p>According to Brown's paper, the bucket width is calculated in a clever way to maintain efficiency: </p><ul><li><p>bucket width is adjusted each time the queue is copied onto a new calendar (when resizing)</p></li><li><p>events are sampled to find the average separation:</p><ul><li><p>For small queues (&#8804; 5 events): sample all events</p></li><li><p>For larger queues: sample 5 + size/10 events (up to max of 25 samples)</p></li><li><p>Dequeue these events, record their priorities, then re-insert them</p></li></ul></li></ul><ul><li><p>there&#8217;s a two-step average calculation:</p><ul><li><p>First calculate initial average separation between sampled events</p></li><li><p>Then recalculate average using only separations smaller than twice the initial average (this handles bimodal distributions by ignoring large gaps)</p></li></ul></li><li><p>and finally, the bucket width = 3.0 * final average</p></li></ul><p>The reasoning behind this method is that we aim to have 2-3 events per bucket on average. Multiplier of 3.0 was found experimentally to give best performance. Ignoring large gaps helps handle skewed/bimodal distributions. Using a sample rather than all events makes the calculation efficient. </p><h4>When does resizing occur?</h4><p>According to Brown's paper, resizing occurs based on queue size thresholds, more specifically: </p><ul><li><p>Growing (Doubling):</p><ul><li><p>Resize occurs when queue size &gt; 2 * number_of_buckets</p></li><li><p>The new calendar gets twice as many buckets</p></li><li><p>Example: If current size is 50 buckets, resize at 101 events</p></li></ul></li><li><p>Shrinking (Halving):</p><ul><li><p>Resize occurs when queue size &lt; number_of_buckets/2</p></li><li><p>The new calendar gets half as many buckets</p></li><li><p>Example: If current size is 50 buckets, resize at 24 events</p></li></ul></li></ul><p>During the resizing process, a new calendar array is created, a new bucket width is calculated using the sampling method, all events are copied to their new bucket positions and finally the switch to the new calendar is done.</p><p>Brown analyzed the impact of resizing, the average event is copied less than 2 times during its lifetime. In the worst case, the queue size oscillates between just above 2^n and just below 2^(n-1), and even in worst case, only about 3 events are copied per hold operation.</p><p>The key innovation of Brown's Calendar Queue was simplifying the two-level approach by using fixed-size buckets instead of dynamic sublists, eliminating the overflow problem through circular wrapping and providing automatic adaptation through bucket resizing. This made the Calendar Queue both simpler to implement and more efficient in practice compared to the TL algorithm, especially for larger queue sizes and varying event distributions.</p><h2>FELT - An optimisation to CQ</h2><p><em>One of the disadvantages of Brown&#8217;s CQs is that resize operation would involve creating a new CQ structure and then moving each item from the old CQ to the new CQ before discarding the old CQ. Hence, such resizes can be costly if the size of the queue is very large</em>. And this is what <em>Hui&#8217;s and Thng&#8217;s FELT (Far Future Event Leaf Tree)</em> [3] structure is trying to solve. </p><p>FELT uses two different structures together to manage events:</p><ol><li><p>A regular calendar queue for near-future events (Primary Tier)</p></li><li><p>A special tree structure for far-future events (FELT) (Secondary Tier)</p></li></ol><p><strong>Primary Tier (Calendar Queue)</strong></p><p>Works like a normal calendar queue with a fixed maximum size (typically 4096 events)</p><p>The FELT primary Calendar Queue works like a normal calendar queue with dual thresholds. The UPPBOUND threshold, typically set at 4096 events, represents the maximum capacity of the primary queue. When exceeded, the system initiates a transfer operation, moving the oldest events into the secondary tree structure. This transfer specifically moves UPPBOUND minus LOWBOUND events, maintaining optimal queue size for performance.</p><p>Conversely, the LOWBOUND threshold, typically set at 256 events, establishes the minimum required event count in the primary queue. When the queue size drops below LOWBOUND, the system initiates a replenishment operation. During replenishment, the system identifies the leaf node containing events with the earliest timestamps in the secondary tier, transfers its entire contents to the primary queue, and removes the depleted leaf node. This process ensures the primary queue maintains sufficient events for efficient operation.</p><p><strong>Secondary Tier (Tree Structure)</strong></p><p>FELT acts as a <strong>semi sorted binary tree</strong>, where the left branch always holds events with higher priority (earlier timestamps) than the right branch. Only the <strong>leaf nodes</strong> store events. These events are kept in an unsorted linked list called <strong>NodeList</strong>. <strong>Parent nodes</strong> act as branching points. They do not store events themselves but maintain information about the minimum timestamp (<strong>MinTimeStamp</strong>) of all events in the branches below them. This helps efficiently route new events to the correct leaf node during insertion. </p><p>FELT is size-based, meaning it manages events based on the number of events stored in the primary CQ. This contrasts with time-based approaches like the Future Event Tree (FET) used in the Dynamic Lazy Calendar Queue (DLCQ), which can lead to inefficiencies when the CQ resizes.</p><pre><code><code>                   [Parent Node(PN): MinTimeStamp(t) = X]
                         /                 \
    [Parent Node: MinTimeStamp = Y]    [Parent Node: MinTimeStamp = Z]
             /   \                                 /  \
 [Leaf Node(LN): MinTimeStamp = A] ... ... [Leaf Node: MinTimeStamp = B]
               |                                    |
[Unsorted Linked List of Events(ULLE)]          [(ULLE)]</code></code></pre><h4>How are events inserted?</h4><p>FELT processes each new event through a two-stage decision process for optimal placement. Initially, the system examines the event's timestamp to determine whether it belongs in the near-future or far-future category. This classification happens by comparing the event's timestamp against a threshold calculated as the current simulation time plus one calendar period.</p><p>For near-future events, the system directs them into the primary calendar queue using standard calendar queue insertion operations. However, if this insertion causes the primary queue to exceed its size threshold, the system automatically transfers the oldest events from the primary queue into the secondary tree structure to maintain optimal queue performance.</p><p>Far-future events take a different path, entering the secondary tree structure where they navigate through internal nodes based on timestamp comparisons. The event travels down the tree, with each internal node guiding it left or right until it reaches an appropriate leaf node. Once at the leaf node, the event is simply appended to an unsorted list maintained at that node:</p><ol><li><p><strong>Start at the Top Node:</strong> The insertion process begins at the topmost node of the FELT structure (<strong>TopNode</strong>).</p></li><li><p><strong>Check if Current Node is a Leaf Node:</strong></p><ol><li><p><strong>If the current node is a leaf node:</strong> The event is inserted into the unsorted linked list (<em>NodeList</em>) at that leaf node.</p></li><li><p><strong>If the current node is a parent node:</strong> Proceed to step 3.</p></li></ol></li><li><p><strong>Compare Event Timestamp with Right Child's MinTimeStamp:</strong></p><ol><li><p><strong>If the event's timestamp is greater than or equal to the MinTimeStamp of the right child node, AND the right child node is not NULL:</strong> Move to the right child node and repeat step 2.</p></li><li><p><strong>Otherwise:</strong> Proceed to step 4.</p></li></ol></li><li><p><strong>Check Left Child:</strong></p><ol><li><p><strong>If the left child node is not NULL:</strong> Move to the left child node and repeat step 2.</p></li><li><p><strong>Otherwise:</strong> Insert the event into the <em>NodeList</em> of the current node (which must be a leaf node).</p></li></ol></li><li><p><strong>Check for Node Splitting:</strong> After the event is inserted, the algorithm checks if the leaf node has exceeded its maximum capacity (MaxSize). When a leaf node has reached its maximum capacity (MaxSize) of events that it can store, which is set a priori, it will spawn two new leaf nodes and split NodeList into 2 and transfer the events into the left and right leaf nodes.</p><ol><li><p><strong>If the node needs splitting:</strong> The splitNode function is called to create two new child leaf nodes and redistribute the events based on their timestamps.</p></li></ol></li></ol><pre><code><code>                  [Parent Node(PN): MinTimeStamp(t) = 10]
                    /                             \
               [PN:t = 5]                     [PN:t = 15]
                /   \                             /   \
       [LN:t = 2]   [LN:t = 7]          [LN:t = 12]   [LN:t = 17]
          |              |                  |           |
     [(ULLE)]         [(ULLE)]          [(ULLE)]      [(ULLE)]</code></code></pre><p>New Event (Timestamp = 8)  </p><ol><li><p>Start at TopNode (MinTimeStamp = 10).  </p></li><li><p>8 &lt; 15 (Right Child's MinTimeStamp), so move to Right Child (MinTimeStamp = 12).</p></li><li><p>Left Child is NULL, so insert event into current node. </p></li></ol><pre><code><code>Result:
                  [Parent Node(PN): MinTimeStamp(t) = 8]
                    /                             \
               [PN:t = 5]                     [PN:t = 8]
                /   \                             /   \
       [LN:t = 2]   [LN:t = 7]          [LN:t = 8]   [LN:t = 17]
          |              |                  |           |
     [(ULLE)]         [(ULLE)]          [(ULLE)]      [(ULLE)]
                                            |   
                                 [New Event (Timestamp = 8)]</code></code></pre><p>When it comes to complexity, the tree traversal is <strong>O(log n)</strong> in best case when tree is balanced and <strong>O(n)</strong> when it&#8217;s a completely skewed tree.</p><p>While the theoretical worst case is <strong>O(n)</strong>, the actual performance in practice tends toward <strong>O(1)</strong> because: the size-based splitting keeps the tree reasonably balanced. The large maxSize (3840) means splits are rare, no sorting is required within leaf nodes and the split cost is bounded by a constant.</p><p>The authors show empirically that FELT maintains near O(1) performance even for large queue sizes and skewed event distributions, performing better than other approaches like DLCQ.</p><h2>The Snoopy CQ</h2><p>The Snoopy Calendar Queue, proposed by <em>Tan, Kah Leong, and Li-Jin Thng. "SNOOPy Calendar Queue."</em> [4], builds upon the concepts of the conventional Calendar Queue (CQ) and the Dynamic Calendar Queue (DCQ), addressing their limitations, particularly in handling skewed event distributions. SNOOPy CQ extends the calendar queue with statistical optimization mechanisms. Instead of using sampling for bucket width calculation like traditional CQ, it tracks operational costs and uses these statistics to optimize queue parameters. The name "SNOOPy" stands for <em>Statistically eNhanced with Optimum Operating Parameter Calendar Queue</em>. The core of SNOOPy CQ lies in its ability to dynamically adjust its operating parameter &#8211; the bucket width &#8211; based on the queue's performance statistics. This adaptive mechanism ensures consistent and efficient performance, achieving near-O(1) complexity even in challenging scenarios.</p><pre><code><code>                       +-----------------------+
                       |      SNOOPy CQ        |
                       +-----------------------+
                                 |  ^
                                 |  |
                                 v  |
                       +-----------------------+
                       |  Enqueue/Dequeue      |
                       |  Operations           |
                       +-----------------------+
                                  |  ^
                                  |  |
                                  v  |
                       +-----------------------+
                       | Performance Statistics|
                       |     (CE, CD)          |
                       +-----------------------+
                                  |  ^
                                  |  |
                                  v  |
      +---------------+-----------------------+----------------+
      |               |                       |                |
      v               v                       v                v
  +-------------+-------------------+--------------+--------------+
  |Trigger Check|  Bucket Width     |Calendar Resize|   Cost       |
  | (CE, CD,    |  Optimization     |  (BW, NB)     |  Calculation |
  | Thresholds) |(Minimize CE + CD) |               |  (CE, CD)    |
  +-------------+-------------------+---------------+--------------+</code></code></pre><ol><li><p><strong>Enqueue/Dequeue Operations:</strong> These are the fundamental operations performed on the SNOOPy CQ. Events are enqueued (added to the queue) based on their timestamps, and the event with the earliest timestamp is dequeued (removed from the queue) for processing.</p></li><li><p><strong>Performance Statistics Collection:</strong> As events are enqueued and dequeued, SNOOPy CQ meticulously tracks two crucial performance metrics:</p><ol><li><p><strong>Average Enqueue Cost (CE):</strong> This represents the average number of events traversed before an insertion can be made in a bucket's linked list.</p></li><li><p><strong>Average Dequeue Cost (CD):</strong> This signifies the average number of buckets that need to be examined before finding the event with the earliest timestamp.</p></li></ol></li><li><p><strong>Trigger Check:</strong> SNOOPy CQ continuously monitors the collected performance statistics (CE and CD). It employs multiple trigger mechanisms:</p><ol><li><p><strong>Inherited from CQ and DCQ:</strong> These triggers are based on thresholds for CE and CD (e.g., if either exceeds a value of 2 or 3), as in the CQ and DCQ structures.</p></li><li><p><strong>Unique to SNOOPy CQ:</strong> Additional triggers are based on the relative difference between CE and CD over multiple slots (time intervals corresponding to a certain number of enqueue or dequeue operations). If the difference exceeds a predefined factor, it signals a need for adjustment.</p></li></ol></li><li><p><strong>Bucket Width Optimization:</strong> When any of the trigger conditions are met, indicating a suboptimal bucket width, SNOOPy CQ initiates its bucket width optimization process. The goal is to find a new bucket width (BW) that minimizes the total cost (CE + CD), keeping the number of buckets (NB) constant. SNOOPy CQ employs a novel approach to determine the optimum BW based on the relationship between CE and CD, as detailed in section 3.1 of "download.pdf".</p></li><li><p><strong>Calendar Resize:</strong> Once the optimal bucket width is calculated, the SNOOPy CQ undergoes a resize operation. A new calendar queue is created with the calculated BW and the same NB as before. Events from the old calendar are then transferred to their appropriate buckets in the new calendar.</p></li><li><p><strong>Cost Calculation:</strong> After each slot (a series of enqueue or dequeue operations), the average enqueue cost (CE) and average dequeue cost (CD) are recalculated based on the accumulated statistics from that slot. These updated costs are then used in subsequent trigger checks and optimization processes.</p></li></ol><h2>Conclusion</h2><p>Starting from the simple Unix V7 cron implementation, each subsequent event scheduling structure addressed specific limitations of its predecessors.</p><p>The Franta-Maly event list introduced sophisticated two-level indexing, achieving O(&#8730;n) complexity through its hierarchical structure. Brown's Calendar Queue (CQ) then simplified this approach with fixed-size buckets and circular wrapping, providing O(1) average performance for uniform distributions.</p><p>FELT built upon CQ's foundation by introducing a dual-tier architecture that efficiently manages near and far-future events, effectively addressing the resize overhead issues. Its size-based approach, rather than time-based, provides consistent performance across varying event distributions.</p><p>SNOOPy CQ represents the current state-of-the-art, employing statistical optimisation to dynamically adjust bucket widths based on operational costs. This adaptive approach ensures robust O(1) performance even under skewed distributions.</p><h2>Data Structures Comparison</h2><h3><strong>Franta-Maly Structure (1977)</strong></h3><h4><strong>Primary Components</strong></h4><ul><li><p>Employs a two-level structure based on indexed lists and the balanced terminal node structure of 3-2 trees.</p></li><li><p>Divides the range of event times into intervals, bounded by "dummy keys (notices)" pointed to by an index list. </p></li><li><p>Each interval further divided into sublists, marked by secondary keys associated with the right boundary dummy key.</p></li></ul><h4><strong>Key Operations Performance</strong></h4><p><strong>Insertion (O(&#8730;n) worst case):</strong></p><ul><li><p>Binary search index array to find appropriate terminal node</p></li><li><p>Linear search within terminal node for insertion position</p></li><li><p>Split terminal node if size exceeds 2&#8730;n</p></li><li><p>Update index pointers if split occurs</p></li></ul><p><strong>Deletion (O(&#8730;n) worst case):</strong></p><ul><li><p>Search index array for target terminal node</p></li><li><p>Remove event from terminal node</p></li><li><p>Merge underfull terminal nodes if necessary</p></li><li><p>Update index pointers after merge</p></li></ul><p><strong>Terminal Node Management:</strong></p><ul><li><p>Split Threshold: 2&#8730;n events</p></li><li><p>Merge Threshold: &#189;&#8730;n events</p></li><li><p>Maintains roughly balanced terminal node sizes</p></li></ul><h4><strong>Performance Bottlenecks</strong></h4><p><strong>Index Array Search:</strong></p><ul><li><p>Binary search cost increases with structure size</p></li><li><p>More frequent searches in skewed distributions</p></li></ul><p><strong>Terminal Node Operations:</strong></p><ul><li><p>Linear search within nodes</p></li><li><p>Split/merge overhead with uneven distributions</p></li></ul><p><strong>Maintenance Overhead:</strong></p><ul><li><p>Index updates after node modifications</p></li><li><p>Balance maintenance across terminal nodes</p></li></ul><h4><strong>Advantages, Limitations and Selection Criteria</strong></h4><p><strong>Advantages:</strong></p><ol><li><p>Bounded Operations:</p><ol><li><p>Guaranteed O(&#8730;n) worst case</p></li><li><p>Predictable performance characteristics</p></li></ol></li><li><p>Memory Locality:</p><ol><li><p>Events clustered in terminal nodes</p></li><li><p>Efficient cache utilisation for sequential access</p></li></ol></li><li><p>Flexible Structure:</p><ol><li><p>Adapts to varying event distributions</p></li><li><p>Self-balancing capabilities</p></li></ol></li></ol><p><strong>Consider Using When:</strong></p><ol><li><p><strong>Predictable Performance is critical:</strong></p><ol><li><p>Operations must have guaranteed bounds</p></li><li><p>Worst-case performance matters more than average case</p></li></ol></li><li><p><strong>Memory Access Patterns are important:</strong></p><ol><li><p>System benefits from clustered event storage</p></li><li><p>Cache efficiency is a priority</p></li></ol></li></ol><p><strong>Limitations: </strong></p><ol><li><p>Complex Implementation:</p><ol><li><p>Significant code complexity for node management</p></li><li><p>Error-prone split/merge operations</p></li></ol></li><li><p>Performance Issues:</p><ol><li><p>High overhead for small event sets</p></li><li><p>Degraded performance with skewed distributions</p></li></ol></li><li><p>Maintenance Overhead:</p><ol><li><p>Frequent index updates</p></li><li><p>Complex rebalancing operations</p></li></ol></li></ol><p><strong>Avoid Using When:</strong></p><ol><li><p>Simple Implementation is preferred:</p><ol><li><p>Calendar queue or modern alternatives offer simpler solutions</p></li><li><p>Development time is constrained</p></li></ol></li><li><p>Optimal Average Performance is required:</p><ol><li><p>Calendar queue provides better average-case performance</p></li><li><p>Event distribution is relatively uniform</p></li></ol></li></ol><h3>Calendar Queue (Brown, 1988)</h3><h4><strong>Primary Components</strong></h4><p>Based on the analogy of a desk calendar, with each "day" represented by a sorted linked list. An array of pointers provides access to each day's linked list.</p><p><strong>Bucket Array:</strong></p><ul><li><p>Fixed-size array of bucket heads</p></li><li><p>Each bucket contains sorted linked list of events</p></li><li><p>Array size maintained as power of 2 for efficient modulo operations</p></li><li><p>Circular structure with wrap-around for year boundaries</p></li></ul><p><strong>Year Mechanism:</strong></p><ul><li><p>Year = NB * BW (Number of buckets * Bucket width)</p></li><li><p>Tracks current year for wrap-around handling</p></li><li><p>Enables infinite future time handling with finite structure</p></li></ul><h4><strong>Key Operations Performance</strong></h4><p><strong>Enqueue (O(n) worst case, O(1) average case):</strong></p><ul><li><p>Calculate virtual bucket using timestamp</p></li><li><p>Map to actual bucket using modulo</p></li><li><p>Insert in sorted order within bucket</p></li><li><p>O(n) complexity when all events are in one bucket</p></li></ul><p><strong>Dequeue (O(n) worst case, O(1) average case):</strong></p><ul><li><p>Start from lastBucket</p></li><li><p>Remove earliest event from current bucket</p></li><li><p>Advance to next bucket if empty</p></li><li><p>Handle year wrap-around when needed</p></li><li><p>O(n) when searching empty buckets</p></li></ul><p><strong>Resize (O(n)):</strong></p><ul><li><p>Triggered when queue size crosses thresholds:</p></li><li><p>Upsize: size &gt; 2 * nbuckets</p></li><li><p>Downsize: size &lt; nbuckets/2</p></li><li><p>Creates new bucket array with doubled/halved size</p></li><li><p>Recalculates bucket width by sampling</p></li><li><p>Redistributes all events</p></li></ul><h4><strong>Performance Bottlenecks</strong></h4><p><strong>Bucket Width Impact:</strong></p><ul><li><p>Too small: Events spread across too many buckets</p></li><li><p>Too large: Too many events per bucket</p></li><li><p>Optimal: 2-3 events per bucket near dequeue point</p></li></ul><p><strong>Distribution Effects:</strong></p><ul><li><p>Uniform: Achieves O(1) performance</p></li><li><p>Skewed: Performance degrades</p></li><li><p>Bimodal: May require frequent resizing</p></li></ul><h4><strong>Advantages, Limitations and Selection Criteria</strong></h4><p><strong>Advantages:</strong></p><ol><li><p>Uniform Distributions - for network simulation, regular event patterns, predictable timings etc</p></li><li><p>Medium-sized Queues - for 1,000 to 10,000 events, stable event counts, regular dequeue patterns</p></li></ol><p><strong>Limitations:</strong></p><ol><li><p>Skewed Distributions - lead to performance degradation, frequent resizing, bucket imbalance</p></li><li><p>Very Large Queues - lead to resize overhead, memory locality issues, width calculation challenges</p></li></ol><h3>FELT (Far Future Event Leaf Tree, 2002)</h3><h4><strong>Primary Components</strong></h4><p>Uses a Primary Tier (Calendar Queue) and a Secondary Tier (Tree Structure). <br><br><strong>Primary Tier (Calendar Queue):</strong></p><ul><li><p>Works like a normal calendar queue with a fixed maximum size (typically 4096 events)</p></li><li><p>Has both an upper limit (UPPBOUND) and lower limit (LOWBOUND) for number of events</p></li><li><p>When too full, moves events to the secondary tier</p></li><li><p>When too empty, gets events back from the secondary tier</p></li></ul><p><strong>Secondary Tier (Tree Structure):</strong></p><ul><li><p>Uses a binary tree where only leaf nodes store events</p></li><li><p>Leaf nodes contain unsorted lists of events</p></li><li><p>Parent nodes just help route to the right leaf node</p></li><li><p>Each node keeps track of the smallest timestamp in its subtree</p></li></ul><h4><strong>Key Operations Performance</strong></h4><p><strong>When Adding a New Event:</strong></p><ol><li><p>Decision Point: System first checks if the event is near-future or far-future</p></li><li><p>Near-Future Events:</p><ol><li><p>Go directly into the calendar queue</p></li><li><p>If this makes the queue too full, oldest events are moved to the tree</p></li></ol></li><li><p>Far-Future Events:</p><ol><li><p>Go into the tree structure</p></li><li><p>Get routed down the tree to the appropriate leaf node</p></li><li><p>Added to that leaf node's unsorted list</p></li></ol></li></ol><p><strong>Near-future events (Primary Calendar Queue): O(1)</strong> average case, as it uses standard calendar queue insertion<br><strong>Far-future events (Secondary Tree): O(log n)</strong> to traverse the tree to the correct leaf node, then O(1) to append to unsorted list<br><strong>Overall: O(1)</strong> for near events, O(log n) for far events<br><br><strong>When Retrieving Events:</strong></p><ol><li><p>Always take events from the calendar queue first</p></li><li><p>When calendar queue gets too empty:</p><ol><li><p>Find the leaf node with earliest events in the tree</p></li><li><p>Move those events to the calendar queue</p></li><li><p>Continue processing from calendar queue</p></li></ol></li><li><p>Primary Calendar Queue: O(1) average case</p><ol><li><p>When primary queue needs replenishment:</p><ol><li><p>Finding minimum leaf node: O(1) using tree's cached minimum timestamps</p></li><li><p>Transferring batch of events: O(k) where k is transfer batch size</p></li></ol></li></ol></li></ol><p><strong>Overall</strong>: Amortized <strong>O(1)</strong> since transfer costs are spread across many operations</p><h4><strong>Performance Bottlenecks</strong></h4><p><strong>Transfer Operations Impact:</strong> <br>When the primary queue hits its UPPBOUND or LOWBOUND thresholds, the transfer operations between tiers can cause significant overhead. These transfers require moving large batches of events between structures and can temporarily pause normal operations. While the cost is amortized, it can cause noticeable performance spikes.<br><br><strong>Leaf Node Management:</strong> <br>When leaf nodes in the secondary tier get too full and need splitting, the operation requires scanning all events in the node to find the average timestamp, then redistributing them. This can be expensive for large leaf nodes and may happen frequently with certain event patterns.<br><br><strong>Threshold Tuning:</strong> <br>Choosing optimal values for UPPBOUND and LOWBOUND is critical but challenging. Poor choices can lead to either too frequent transfers or inefficient primary queue operation, significantly impacting performance.<br><br>These bottlenecks become particularly apparent in scenarios with:<br>- Highly skewed temporal distributions<br>- Memory-constrained environments<br>- Large numbers of far-future events</p><h4><strong>Advantages, Limitations and Selection Criteria</strong></h4><p><strong>Optimal Use Cases</strong></p><ol><li><p>Large Event Sets (10,000 events)</p><ol><li><p>Wide timestamp distribution</p></li><li><p>Frequent far-future events</p></li></ol></li><li><p>Variable Distributions:</p><ol><li><p>Skewed timestamp patterns</p></li><li><p>Mixed temporal localities</p></li><li><p>Dynamic workload patterns</p></li></ol></li></ol><p><strong>Limitations</strong></p><ol><li><p>Implementation Complexity:</p><ol><li><p>Complex maintenance logic</p></li><li><p>Debugging challenges</p></li><li><p>Higher development overhead</p></li></ol></li><li><p>Resource Requirements:</p><ol><li><p>Additional memory overhead</p></li><li><p>Complex pointer management</p></li><li><p>Transfer operation costs</p></li></ol></li></ol><h3>SNOOPy Calendar Queue (2000)</h3><h4><strong>Primary Components</strong></h4><p>The structure maintains traditional calendar queue elements plus statistical tracking:<br><br><strong>Calendar Base Structure:</strong></p><ul><li><p>Array of buckets containing sorted event lists</p></li><li><p>Each bucket represents a time interval</p></li><li><p>Year size = number of buckets &#215; bucket width</p></li></ul><p><strong>Statistical Enhancement Layer:</strong></p><ul><li><p>CE (Enqueue Cost): Tracks average number of events traversed during insertion</p></li><li><p>CD (Dequeue Cost): Tracks average number of empty buckets traversed during dequeuing</p></li><li><p>Moving average window over multiple operations</p></li><li><p>Performance metrics for bucket width optimisation</p></li></ul><h4><strong>Key Operations Performance</strong></h4><p><strong>Enqueue Process (O(1) average case):</strong></p><ul><li><p>Calculates target bucket using timestamp</p></li><li><p>Inserts event in sorted order within bucket</p></li><li><p>Updates enqueue cost statistics based on traversal length</p></li><li><p>Triggers resize if statistical thresholds exceeded</p></li></ul><p><strong>Dequeue Process (O(1) average case):</strong></p><ul><li><p>Retrieves earliest event from current bucket</p></li><li><p>Advances through empty buckets if necessary</p></li><li><p>Updates dequeue cost statistics</p></li><li><p>May trigger optimisation based on performance metrics</p></li></ul><p><strong>Resize Operation (O(n) when restructuring):</strong></p><ul><li><p>Triggered by statistical cost metrics rather than just size</p></li><li><p>Uses performance history to calculate optimal bucket width</p></li><li><p>Redistributes events across new structure</p></li><li><p>Resets statistical counters after resize</p></li></ul><h4><strong>Performance Bottlenecks</strong></h4><p><strong>Statistical Overhead:</strong></p><ul><li><p>Continuous cost tracking adds per-operation overhead</p></li><li><p>Moving average calculations require additional computation</p></li><li><p>Statistical threshold checks on every operation</p></li></ul><p>Resize Decisions:</p><ul><li><p>More complex than traditional CQ resize triggers</p></li><li><p>May require more frequent resizes initially while optimising</p></li><li><p>Statistical calculation overhead during resize operations</p></li></ul><p>Dynamic Adaptation:</p><ul><li><p>Initial period of suboptimal performance while gathering statistics</p></li><li><p>May oscillate between different configurations before settling</p></li><li><p>Additional memory references for statistical tracking</p></li></ul><h4><strong>Advantages, Limitations and Selection Criteria</strong></h4><p><strong>Advantages:</strong></p><ul><li><p>Robust Performance:</p><ul><li><p>Better handling of skewed distributions than traditional CQ</p></li><li><p>Self-tuning capability reduces manual parameter tuning</p></li><li><p>More consistent performance across varying workloads</p></li></ul></li><li><p>Adaptive Optimisation:</p><ul><li><p>Automatically adjusts to changing event patterns</p></li><li><p>Reduces impact of poor initial parameter choices</p></li><li><p>Maintains efficiency under varying conditions</p></li></ul></li><li><p>Statistical Insight:</p><ul><li><p>Provides performance metrics for monitoring</p></li><li><p>Enables informed optimization decisions</p></li><li><p>Can predict and prevent performance degradation</p></li></ul></li></ul><p><strong>Best Used When:</strong></p><ul><li><p>Event distribution is unknown or varies</p></li><li><p>Long-running simulations justify optimization overhead</p></li><li><p>Performance consistency is critical</p></li><li><p>Manual tuning is impractical</p></li></ul><p><strong>Limitations:</strong></p><ul><li><p>Implementation Complexity:</p><ul><li><p>More complex than basic calendar queue</p></li><li><p>Additional overhead for statistical tracking</p></li><li><p>More difficult to debug and maintain</p></li></ul></li></ul><p><strong>Avoid When:</strong></p><ul><li><p>Simple, known event distributions</p></li><li><p>Short-running simulations</p></li><li><p>Memory or CPU resources are very constrained</p></li><li><p>Implementation simplicity is priority</p></li></ul><h3>Resources</h3><p>[1] Franta, W. R., and Kurt Maly. "An Efficient Data Structure for the Simulation Event Set." Communications of the ACM 20, no. 8 (August 1977): 596-602.</p><p>[2] Brown, Randy. "Calendar Queues: A Fast O(1) Priority Queue Implementation for the Simulation Event Set Problem." Communications of the ACM 31, no. 10 (October 1988): 1220-1227.</p><p>[3] Hui, Timothy Chee-Kin, and Ian Li-Jin Thng. "FELT: A Far Future Event List Structure Optimized for Calendar Queues." SIMULATION: Transactions of The Society for Modeling and Simulation International 78, no. 6 (June 2002): 343-361.</p><p>[4] Tan, Kah Leong, and Li-Jin Thng. "SNOOPy Calendar Queue." In Proceedings of the 2000 Winter Simulation Conference, edited by J. A. Joines, R. R. Barton, K. Kang, and P. A. Fishwick, 487-495. IEEE, 2000.</p>]]></content:encoded></item><item><title><![CDATA[Payments Systems at Scale: Lessons from Uber's Unified Platform]]></title><description><![CDATA[On the story of how Uber's engineering team transformed a maze of payment systems into a unified platform that powers millions of transactions daily]]></description><link>https://blog.diana-enache.com/p/payments-systems-at-scale-lessons</link><guid isPermaLink="false">https://blog.diana-enache.com/p/payments-systems-at-scale-lessons</guid><dc:creator><![CDATA[Diana Darie]]></dc:creator><pubDate>Sat, 16 Nov 2024 15:52:57 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce68a52e-d971-4f41-810c-bf3e95a02962_1600x989.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Picture this: You're at a restaurant that accepts credit cards for dine-in but only cash for takeout, Apple Pay for drinks but not desserts. Sounds absurd? This was essentially Uber's reality across its services.</p><p>As Uber evolved from a simple ride-hailing app into a super-app offering food delivery, grocery shopping, and even car rentals, each new service built its own payment system. The result? A labyrinth of 70 different payment endpoints, each speaking its own language.</p><p>This fragmentation created real-world headaches. A user could pay for an immediate ride with Apple Pay but couldn't use it for a scheduled pickup. Popular payment methods like PIX (Brazil) and UPI (India) worked inconsistently across services. For any new payment feature or compliance requirement that needed to be integrated, engineers would have to spend countless more hours maintaining this new duplicate code.</p><p>The cost wasn't just technical. When the European Union mandated Strong Customer Authentication for transactions, requiring features like fingerprinting and biometric verification, it became clear: Uber needed to revolutionize its payment infrastructure or risk losing hundreds of millions in revenue.</p><h3>Unified Checkout - One Gateway to Rule Them All</h3><p>What Uber&#8217;s engineering team created is a payment universal translator, which they called <strong>Unified Checkou</strong>t. The way it works is that instead of each service (rides, eats, rentals) handling payments differently, everything flows through one complex system.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!G1rJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3bb6ca8b-883f-42ce-8c95-4a51212b3b68_1600x859.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!G1rJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3bb6ca8b-883f-42ce-8c95-4a51212b3b68_1600x859.png 424w, https://substackcdn.com/image/fetch/$s_!G1rJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3bb6ca8b-883f-42ce-8c95-4a51212b3b68_1600x859.png 848w, https://substackcdn.com/image/fetch/$s_!G1rJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3bb6ca8b-883f-42ce-8c95-4a51212b3b68_1600x859.png 1272w, https://substackcdn.com/image/fetch/$s_!G1rJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3bb6ca8b-883f-42ce-8c95-4a51212b3b68_1600x859.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!G1rJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3bb6ca8b-883f-42ce-8c95-4a51212b3b68_1600x859.png" width="1456" height="782" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3bb6ca8b-883f-42ce-8c95-4a51212b3b68_1600x859.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:782,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Image&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="Image" title="Image" srcset="https://substackcdn.com/image/fetch/$s_!G1rJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3bb6ca8b-883f-42ce-8c95-4a51212b3b68_1600x859.png 424w, https://substackcdn.com/image/fetch/$s_!G1rJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3bb6ca8b-883f-42ce-8c95-4a51212b3b68_1600x859.png 848w, https://substackcdn.com/image/fetch/$s_!G1rJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3bb6ca8b-883f-42ce-8c95-4a51212b3b68_1600x859.png 1272w, https://substackcdn.com/image/fetch/$s_!G1rJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3bb6ca8b-883f-42ce-8c95-4a51212b3b68_1600x859.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">Uber&#8217;s architecture without and with Unified Checkout (<a href="https://www.uber.com/en-GB/blog/unified-checkout/">Source</a>)</figcaption></figure></div><p>This payments orchestration layer while it helps to process millions of transactions and to maintain consistency across all services, it keeps individual services blissfully unaware of the underlying complexity.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!S1wW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce68a52e-d971-4f41-810c-bf3e95a02962_1600x989.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!S1wW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce68a52e-d971-4f41-810c-bf3e95a02962_1600x989.png 424w, https://substackcdn.com/image/fetch/$s_!S1wW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce68a52e-d971-4f41-810c-bf3e95a02962_1600x989.png 848w, https://substackcdn.com/image/fetch/$s_!S1wW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce68a52e-d971-4f41-810c-bf3e95a02962_1600x989.png 1272w, https://substackcdn.com/image/fetch/$s_!S1wW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce68a52e-d971-4f41-810c-bf3e95a02962_1600x989.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!S1wW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce68a52e-d971-4f41-810c-bf3e95a02962_1600x989.png" width="1456" height="900" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ce68a52e-d971-4f41-810c-bf3e95a02962_1600x989.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:900,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Image&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Image" title="Image" srcset="https://substackcdn.com/image/fetch/$s_!S1wW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce68a52e-d971-4f41-810c-bf3e95a02962_1600x989.png 424w, https://substackcdn.com/image/fetch/$s_!S1wW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce68a52e-d971-4f41-810c-bf3e95a02962_1600x989.png 848w, https://substackcdn.com/image/fetch/$s_!S1wW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce68a52e-d971-4f41-810c-bf3e95a02962_1600x989.png 1272w, https://substackcdn.com/image/fetch/$s_!S1wW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce68a52e-d971-4f41-810c-bf3e95a02962_1600x989.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Architecture of the Unified Checkout (<a href="https://www.uber.com/en-GB/blog/unified-checkout/">source</a>)</figcaption></figure></div><p>The architecture revolves around a chain of microservices that handle everything from payment profile preparation to risk evaluation. When a user starts a transaction, the platform exchanges transactional data with third-party processors, generates authentication tokens, and coordinates with risk systems to determine the optimal payment strategy. The system is able to adapt its approach based on the risk algorithms, whether if it&#8217;s for an authorization hold or an upfront charge.</p><p>One notable capability of the Unified Checkout is that it provides <strong>two distinct integration paths.</strong></p><ul><li><p>The <strong>modular approach</strong> allows services to embed pre-built components into their existing checkout flows, maintaining their unique user experience while leveraging the unified payment infrastructure.</p></li><li><p>For newer or smaller services, the <strong>hosted solution</strong> provides a complete out-of-the-box payment experience, accelerating time-to-market without compromising on functionality.</p></li></ul><p>Another key advantage is the <strong>"Checkout Actions" framework</strong> - a stateless system that orchestrates complex payment flows, from two-factor authentication to identity challenges, this framework handles every possible payment scenario while maintaining a consistent user experience.</p><p>By treating each Uber service as an external company, the platform maintains strict boundaries between payment logic and business operations. This architectural decision forced the team to build a solution that could handle any payment scenario while remaining service-agnostic, and hence building a good foundation for future payment innovations.</p><h3>The Business Impact</h3><p>The Unified Checkout delivered a remarkable 3% increase in checkout conversion rate and a 4.5% improvement in session recovery, which meant saving hundreds of millions in additional annual revenue. These results were shown in an experiment on UberEats, where the team compared user behaviour between the old and new systems, leading to rapid adoption across all services.</p><p>This transformation dramatically simplified the payment landscape at Uber. Adding another payment method like Apple Pay doesn&#8217;t require a full implementation anymore, but only some configuration changes. Moving away from 70 endpoints to one single unified system streamlined operations and changed on a fundamental level how Uber does payments. Duplicate development work vanished. The launch of new payment methods accelerated dramatically. A consistent user experience across services built stronger trust with customers. Payment method decisions shifted from technical limitations to pure strategy, allowing Uber to optimise its offerings based on market needs rather than implementation constraints.</p><p>Maintenance costs plummeted as teams no longer needed to maintain multiple implementations. Compliance became more straightforward, error rates dropped significantly, and customer support issues decreased. And probably most importantly, new services could now launch faster, equipped with a complete payment infrastructure from day one.</p><h3>Lessons Learnt</h3><p>It comes a time in a company&#8217;s scaling journey where maintaining multiple systems becomes more expensive than building a unified platform. For Uber, this moment came when they faced 70 different payment endpoints across their services, each requiring separate maintenance and updates.</p><p>Uber's experience demonstrates how external pressures, like EU regulations, can serve as catalysts for positive change. What began as a compliance requirement evolved into a platform that generated hundreds of millions in additional revenue.</p><p>Looking toward the future, the key is creating modular systems that can evolve with changing requirements, while maintaining a clear separation between business logic and payment processing. This separation allows for easier updates and maintenance as regulatory requirements change or new payment methods emerge.</p><p>The most valuable lesson from Uber's journey is recognizing that technical debt isn't always a burden &#8211; it can be a signal that your system is ready for platformization. When multiple teams struggle with similar problems, it might be time to step back and consider a unified approach. </p><p>The Uber article is available here:<br><strong><a href="https://www.uber.com/en-GB/blog/unified-checkout/">Unified Checkout: Streamlining Uber&#8217;s Payment Ecosystem</a></strong></p><div><hr></div><h3>Similar stories you might enjoy &#128218;</h3><ul><li><p><a href="https://stripe.com/blog/how-stripes-document-databases-supported-99.999-uptime-with-zero-downtime-data-migrations?utm_source=blog.quastor.org&amp;utm_medium=referral&amp;utm_campaign=the-architecture-of-stripe-s-document-database">How Stripe&#8217;s document databases supported 99.999% uptime with zero-downtime data migrations</a></p></li><li><p><a href="https://medium.com/paypal-tech/scaling-kafka-to-support-paypals-data-growth-a0b4da420fab">How PayPal Scaled Kafka to 1.3 Trillion Messages a Day</a></p></li><li><p><a href="https://monzo.com/blog/vertically-scaling-ordered-consumption-using-kafka">How Monzo vertically scaled ordered consumption using Kafka</a></p></li></ul>]]></content:encoded></item><item><title><![CDATA[Understanding the Dual-Write Challenge in Multi-System Environments]]></title><description><![CDATA[On the risks of data consistency, the causes behind synchronisation issues, and strategies to mitigate these problems.]]></description><link>https://blog.diana-enache.com/p/understanding-the-dual-write-challenge</link><guid isPermaLink="false">https://blog.diana-enache.com/p/understanding-the-dual-write-challenge</guid><dc:creator><![CDATA[Diana Darie]]></dc:creator><pubDate>Sun, 25 Aug 2024 07:32:08 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/b3ff8862-4f4d-4a4f-9879-616497ba71d3_2420x736.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3>The Dual-Write Problem</h3><p>The dual-write problem is a critical issue that arises when updating multiple systems simultaneously. This challenge significantly impacts data consistency, system reliability, and overall performance in modern software architectures.</p><p>At its core, the dual-write problem stems from the difficulty of ensuring that all write operations across different systems either succeed or fail together. Traditional database transactions provide atomicity within a single database, but this guarantee doesn't extend to multiple systems. This limitation creates a risk of <em><strong>partial updates</strong></em>, which can lead to <em><strong>data inconsistencies</strong></em> and compromise the integrity of the overall system.</p><p>Failure scenarios further complicate the dual-write problem. System crashes, network failures, and partial outages can occur at any point during the update process, potentially leaving systems out of sync. For instance, if a failure occurs after writing to one system but before updating another, the result is inconsistent data across the environment.</p><p>To illustrate the dual-write problem, consider a common scenario in microservice architectures: updating a database and sending a notification message. Ideally, these operations should be atomic to ensure data consistency and reliability. However, the lack of a unified transaction mechanism across different systems makes achieving this atomicity challenging.</p><ul><li><p>If the database update is successful but the event notification fails, the downstream service will not be aware of the change, and the system can enter an inconsistent state.</p></li><li><p>If the database update fails but the event notification is sent, data could get corrupted, which might affect the reliability of the system.</p></li></ul><p>As organisations continue to adopt microservices and distributed architectures, addressing the dual-write problem becomes increasingly crucial. </p><p></p><h3>The Transactional Outbox Pattern</h3><p>One way to solve this is through the Transactional Outbox pattern. If we have a database that supports transactional updates, then we can use it to overcome the dual-write problem. </p><p>Let&#8217;s take the example of a food delivery company system. When a customer places an order, several things need to happen: 1. The order details need to be saved in the database 2. A notification needs to be sent to the restaurant 3. The customer should receive an order confirmation 4. The order should be made available for driver assignment and so on. </p><p>The <strong>Order Service</strong> receives the order request. Then it starts a database transaction. It inserts the order details into the <strong>Orders table</strong> and in the same transaction, it also inserts messages into the <strong>Outbox table</strong>. These messages might include: a) OrderCreated event b) NotifyRestaurant message c) SendCustomerConfirmation message. The database transaction is committed, ensuring both the order and the outbox messages are saved atomically. </p><p>The <strong>Publisher Service</strong> runs continuously or at frequent intervals. It queries the Outbox table for unpublished messages. When it finds messages, it reads them and publishes them to the <strong>Message Broker</strong>. After successful publication, it marks the messages as processed or deletes them from the Outbox table.</p><p>The <strong>Message Broker</strong> receives the published messages from the <strong>Publisher Service</strong> and routes these messages to the appropriate queues or topics.</p><p>Then we have all the <strong>Downstream Services</strong>. A <strong>Restaurant Service</strong> might subscribe to the "OrderCreated" event. When received, it notifies the restaurant about the new order. A <strong>Notification Service</strong> might pick up the "SendCustomerConfirmation" message and sends an order confirmation to the customer. A <strong>Driver Assignment Service</strong> might listen for "OrderCreated" events to begin the process of assigning a driver.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!gQ39!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ff3e94b-29d5-4cc0-a574-ac5b3e39db4a_1600x559.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gQ39!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ff3e94b-29d5-4cc0-a574-ac5b3e39db4a_1600x559.png 424w, https://substackcdn.com/image/fetch/$s_!gQ39!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ff3e94b-29d5-4cc0-a574-ac5b3e39db4a_1600x559.png 848w, https://substackcdn.com/image/fetch/$s_!gQ39!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ff3e94b-29d5-4cc0-a574-ac5b3e39db4a_1600x559.png 1272w, https://substackcdn.com/image/fetch/$s_!gQ39!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ff3e94b-29d5-4cc0-a574-ac5b3e39db4a_1600x559.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!gQ39!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ff3e94b-29d5-4cc0-a574-ac5b3e39db4a_1600x559.png" width="1456" height="509" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6ff3e94b-29d5-4cc0-a574-ac5b3e39db4a_1600x559.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:509,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!gQ39!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ff3e94b-29d5-4cc0-a574-ac5b3e39db4a_1600x559.png 424w, https://substackcdn.com/image/fetch/$s_!gQ39!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ff3e94b-29d5-4cc0-a574-ac5b3e39db4a_1600x559.png 848w, https://substackcdn.com/image/fetch/$s_!gQ39!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ff3e94b-29d5-4cc0-a574-ac5b3e39db4a_1600x559.png 1272w, https://substackcdn.com/image/fetch/$s_!gQ39!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6ff3e94b-29d5-4cc0-a574-ac5b3e39db4a_1600x559.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">A Transactional Outbox Pattern for a Food Delivery System</figcaption></figure></div><p><strong>When to use:</strong></p><ul><li><p>You need to ensure consistency between your database and a message broker.</p></li><li><p>You want to implement reliable messaging in a microservices architecture.</p></li><li><p>You need to guarantee that a message is sent if and only if a database transaction commits.</p></li></ul><p><strong>Pros:</strong></p><ul><li><p>Ensures consistency between database and messaging system.</p></li><li><p>Works well with existing relational databases.</p></li><li><p>Simpler to implement than full event sourcing.</p></li><li><p>Doesn't require changing your entire architecture.</p></li></ul><p><strong>Cons:</strong></p><ul><li><p>Doesn't provide a full audit trail like event sourcing.</p></li><li><p>Requires polling or additional mechanisms to publish messages.</p></li><li><p>Can add complexity to your database schema.</p></li></ul><p></p><h3>Change Data Capture</h3><p>Store the state record to a data store that supports CDC. Then the CDC infrastructure will notify external systems of the changes. One such example would be DynamoDB, using its DynamoDB Streams.</p><p>Coming back to the example earlier, in a CDC approach, the <strong>Order Service</strong> receives the order request, it processes the order and inserts the order details into the <strong>Orders table</strong> in the database. The <strong>CDC</strong> <strong>tool</strong> continuously monitors the database's transaction log. When it detects a change in the Orders table (in this case, a new order insertion), it captures this change. The CDC tool transforms the captured change into a structured event message and publishes the captured change event to a <strong>Message Broker/Streams</strong>. The event contains details about the new order, such as order ID, customer ID, restaurant ID, and other relevant information. And same as above, multiple <strong>Downstream Services</strong> can then subscribe to the Order change events from the Message Broker.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!RWBt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdda434c7-c642-4f8f-bda2-b1daa2f2b3df_1600x543.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!RWBt!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdda434c7-c642-4f8f-bda2-b1daa2f2b3df_1600x543.png 424w, https://substackcdn.com/image/fetch/$s_!RWBt!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdda434c7-c642-4f8f-bda2-b1daa2f2b3df_1600x543.png 848w, https://substackcdn.com/image/fetch/$s_!RWBt!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdda434c7-c642-4f8f-bda2-b1daa2f2b3df_1600x543.png 1272w, https://substackcdn.com/image/fetch/$s_!RWBt!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdda434c7-c642-4f8f-bda2-b1daa2f2b3df_1600x543.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!RWBt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdda434c7-c642-4f8f-bda2-b1daa2f2b3df_1600x543.png" width="1456" height="494" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dda434c7-c642-4f8f-bda2-b1daa2f2b3df_1600x543.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:494,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!RWBt!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdda434c7-c642-4f8f-bda2-b1daa2f2b3df_1600x543.png 424w, https://substackcdn.com/image/fetch/$s_!RWBt!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdda434c7-c642-4f8f-bda2-b1daa2f2b3df_1600x543.png 848w, https://substackcdn.com/image/fetch/$s_!RWBt!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdda434c7-c642-4f8f-bda2-b1daa2f2b3df_1600x543.png 1272w, https://substackcdn.com/image/fetch/$s_!RWBt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdda434c7-c642-4f8f-bda2-b1daa2f2b3df_1600x543.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">A CDC Approach for a Food Delivery System</figcaption></figure></div><p><strong>When to use:</strong></p><ul><li><p>You want to track changes in your database for replication or integration purposes.</p></li><li><p>You need to sync data between different systems in near real-time.</p></li><li><p>You want to implement event-driven architectures without changing your existing systems.</p></li><li><p>You need to create data lakes or data warehouses from operational databases.</p></li></ul><p><strong>Pros:</strong></p><ul><li><p>Non-intrusive - can be implemented without changing existing applications.</p></li><li><p>Captures all changes, including those made outside your application.</p></li><li><p>Can be used with legacy systems.</p></li><li><p>Supports real-time data integration.</p></li></ul><p><strong>Cons:</strong></p><ul><li><p>May not capture the full business context of changes.</p></li><li><p>Can be complex to set up and manage.</p></li><li><p>May impact database performance. CDC can add some overhead to the database, as it needs to read the transaction logs.</p></li><li><p>Might require specific database features or additional tools.</p></li><li><p>When the Orders table schema changes, downstream consumers need to be prepared to handle both old and new event formats.</p></li></ul><p></p><h3>Event Sourcing</h3><p>Event sourcing is a pattern for storing data or changes to data as events in an append-only log. This represents a business decision to accept the request and start processing it.  </p><blockquote><p><em>The idea of event sourcing is that the event log is the source of truth, and all other databases are projections of the event log. Any write must first be made to the event log. After this write succeeds, one or more event handlers consume this new event and writes it to the other databases. </em>(<em>Cloud Native Patterns</em> by Cornelia Davis (Manning Publications, 2019))</p></blockquote><p>In event sourcing, every change to an entity's state is captured as a discrete, fine-grained event. These events are not merely notifications, each event represents a specific, atomic alteration to the entity's state.</p><p>As these state-changing events occur, they are published to interested parties and simultaneously persisted in a chronological log. This log becomes the source of truth for all the changes that have occurred to the entity over time. It's akin to a detailed historical ledger, capturing every nuance of the entity's evolution.</p><p>The power of event sourcing lies in its ability to reconstruct an entity state. Subscribers to this event log can process the sequence of events to derive the current state of an entity at any given point in time. By "replaying" the events in order, these subscribers can build a complete and accurate picture of the entity's current condition.</p><p>Take the design of an order processing system for a food delivery platform as an example. Event sourcing simplifies this process. All these events (orderCreated, orderAcceptedByRestaurant, orderPreparing etc.) are stored in an append-only log. Each event contains details like timestamp, entity_id, event_type and relevant data. The current state of an order can be reconstructed by replaying all events for that order from the beginning.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Bm2_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9705934d-1190-46c9-a115-13f3930d7dba_1600x541.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Bm2_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9705934d-1190-46c9-a115-13f3930d7dba_1600x541.png 424w, https://substackcdn.com/image/fetch/$s_!Bm2_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9705934d-1190-46c9-a115-13f3930d7dba_1600x541.png 848w, https://substackcdn.com/image/fetch/$s_!Bm2_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9705934d-1190-46c9-a115-13f3930d7dba_1600x541.png 1272w, https://substackcdn.com/image/fetch/$s_!Bm2_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9705934d-1190-46c9-a115-13f3930d7dba_1600x541.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Bm2_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9705934d-1190-46c9-a115-13f3930d7dba_1600x541.png" width="1456" height="492" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9705934d-1190-46c9-a115-13f3930d7dba_1600x541.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:492,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!Bm2_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9705934d-1190-46c9-a115-13f3930d7dba_1600x541.png 424w, https://substackcdn.com/image/fetch/$s_!Bm2_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9705934d-1190-46c9-a115-13f3930d7dba_1600x541.png 848w, https://substackcdn.com/image/fetch/$s_!Bm2_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9705934d-1190-46c9-a115-13f3930d7dba_1600x541.png 1272w, https://substackcdn.com/image/fetch/$s_!Bm2_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9705934d-1190-46c9-a115-13f3930d7dba_1600x541.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Event Sourcing Architecture for a Food Delivery Platform</figcaption></figure></div><p><strong>When to use:</strong></p><ul><li><p>You need a complete audit trail of all changes.</p></li><li><p>You want to reconstruct past states of your system.</p></li><li><p>Your domain model is complex with many state transitions.</p></li><li><p>You need to support temporal queries (e.g., "What was the state at time X?").</p></li><li><p>You want to enable easy implementation of new features based on historical data.</p></li></ul><p><strong>Pros:</strong></p><ul><li><p>Provides a full history of changes.</p></li><li><p>Enables easy debugging and auditing.</p></li><li><p>Allows for event replay and system recovery.</p></li><li><p>Supports complex domain modelling.</p></li></ul><p>Cons:</p><ul><li><p>Can be complex to implement and maintain.</p></li><li><p>May require more storage.</p></li><li><p>Querying current state can be slower (mitigated by snapshots).</p></li></ul><p></p><h3>Listen to Yourself </h3><p>The Listen to Yourself pattern is a variation of event-driven architecture that aims to solve the problem of data consistency between a service's database and its published events. The service publishes events to a message broker as part of its operations. The service then subscribes to its own events from the message broker. Upon receiving its own event, the service updates its database.</p><p>The <strong>Order Service</strong> receives the order request. It prepares the order data and instead of writing directly to the database, it publishes an "OrderCreated" event to the <strong>Message Broker</strong>. This event contains all necessary order details (order ID, customer ID, restaurant ID, items, total, etc.). The <strong>Message Broker</strong> receives the "OrderCreated" event from the <strong>Order Service</strong> and makes the event available to all subscribed services, including the <strong>Order Service</strong> itself. The <strong>Order Service</strong> subscribes to its own "OrderCreated" events. When it receives the event it just published: a) It writes the order details to the Orders table in the database. b) It updates its internal state if necessary. Multiple <strong>Downstream Services</strong> also subscribe to the "OrderCreated" events.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!inMD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80f1a8cd-d0dd-40f9-bb8c-ade74406b3c9_1600x467.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!inMD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80f1a8cd-d0dd-40f9-bb8c-ade74406b3c9_1600x467.png 424w, https://substackcdn.com/image/fetch/$s_!inMD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80f1a8cd-d0dd-40f9-bb8c-ade74406b3c9_1600x467.png 848w, https://substackcdn.com/image/fetch/$s_!inMD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80f1a8cd-d0dd-40f9-bb8c-ade74406b3c9_1600x467.png 1272w, https://substackcdn.com/image/fetch/$s_!inMD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80f1a8cd-d0dd-40f9-bb8c-ade74406b3c9_1600x467.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!inMD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80f1a8cd-d0dd-40f9-bb8c-ade74406b3c9_1600x467.png" width="1456" height="425" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/80f1a8cd-d0dd-40f9-bb8c-ade74406b3c9_1600x467.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:425,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!inMD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80f1a8cd-d0dd-40f9-bb8c-ade74406b3c9_1600x467.png 424w, https://substackcdn.com/image/fetch/$s_!inMD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80f1a8cd-d0dd-40f9-bb8c-ade74406b3c9_1600x467.png 848w, https://substackcdn.com/image/fetch/$s_!inMD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80f1a8cd-d0dd-40f9-bb8c-ade74406b3c9_1600x467.png 1272w, https://substackcdn.com/image/fetch/$s_!inMD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F80f1a8cd-d0dd-40f9-bb8c-ade74406b3c9_1600x467.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Listen to Yourself pattern applied to a Food Delivery System</figcaption></figure></div><p><strong>How it's different:</strong></p><ul><li><p>Unlike the Transactional Outbox pattern, it doesn't require a separate outbox table in the database.</p></li><li><p>It's simpler than full Event Sourcing but still provides a level of eventual consistency.</p></li><li><p>It differs from CDC in that the service actively publishes events, rather than relying on database log parsing.</p></li></ul><p><strong>Pros:</strong></p><ul><li><p>Simplifies the architecture by using the message broker as the source of truth.</p></li><li><p>Ensures eventual consistency between the published events and the database state.</p></li><li><p>Can be easier to implement than some other patterns.</p></li></ul><p><strong>Cons:</strong></p><ul><li><p>There's a potential for temporary inconsistency between the event being published and the database being updated.</p></li><li><p>It may introduce additional latency due to the round-trip through the message broker.</p></li><li><p>It can be more difficult to debug, as the flow of data is less straightforward.</p></li></ul><p></p><h3>Conclusion</h3><p>We had a look at the different solutions that can be used to solve the dual-write problem. Which approach is used varies based on a given use case, specific requirements or any constraints of the system being designed or modified. To wrap things up, below is a comparison that might help you in making your decision:</p><p><strong>Data Consistency:</strong> </p><ul><li><p><strong>Event Sourcing:</strong> High consistency, events are the source of truth</p></li><li><p><strong>Transactional Outbox:</strong> Strong consistency between database and messaging</p></li><li><p><strong>Listen to Yourself:</strong> Eventual consistency, with potential for brief inconsistencies</p></li><li><p><strong>CDC:</strong> Eventual consistency, with potential for small delays</p></li></ul><p><strong>Complexity of Implementation:</strong> </p><ul><li><p><strong>Event Sourcing:</strong> High - requires significant architectural changes</p></li><li><p><strong>Transactional Outbox:</strong> Moderate - requires additional table and message relay process</p></li><li><p><strong>Listen to Yourself:</strong> Low to Moderate - requires event publishing and self-subscription</p></li><li><p><strong>CDC:</strong> Moderate - requires CDC tool setup and configuration</p></li></ul><p><strong>Performance Impact:</strong> </p><ul><li><p><strong>Event Sourcing:</strong> Can be high for read operations, depending on implementation</p></li><li><p><strong>Transactional Outbox:</strong> Low impact on write operations, additional load for message relay</p></li><li><p><strong>Listen to Yourself:</strong> Moderate - additional network round-trip for each operation</p></li><li><p><strong>CDC:</strong> Low to Moderate - some overhead on database for log reading</p></li></ul><p><strong>Scalability:</strong> </p><ul><li><p><strong>Event Sourcing:</strong> Highly scalable, especially for write operations</p></li><li><p><strong>Transactional Outbox:</strong> Scalable, with separate scaling for application and message relay</p></li><li><p><strong>Listen to Yourself:</strong> Scalable, but may require careful management of self-subscriptions</p></li><li><p><strong>CDC:</strong> Highly scalable, especially for high-volume changes</p></li></ul><p><strong>Auditability:</strong> </p><ul><li><p><strong>Event Sourcing:</strong> Excellent - full history of all changes</p></li><li><p><strong>Transactional Outbox:</strong> Good - outbox can serve as an audit log</p></li><li><p><strong>Listen to Yourself:</strong> Good - events can serve as an audit log</p></li><li><p><strong>CDC:</strong> Excellent - captures all database changes</p></li></ul><p><strong>Ability to Reconstruct Past States:</strong> </p><ul><li><p><strong>Event Sourcing:</strong> Excellent - core feature of the pattern</p></li><li><p><strong>Transactional Outbox:</strong> Limited - not a primary feature</p></li><li><p><strong>Listen to Yourself:</strong> Possible but not straightforward</p></li><li><p><strong>CDC:</strong> Possible if all changes are retained, but not a primary feature</p></li></ul><p><strong>Impact on Existing Systems:</strong> </p><ul><li><p><strong>Event Sourcing:</strong> High - requires fundamental architectural changes</p></li><li><p><strong>Transactional Outbox:</strong> Moderate - requires changes to data access layer</p></li><li><p><strong>Listen to Yourself:</strong> Moderate - requires changes to service logic</p></li><li><p><strong>CDC:</strong> Low - can often be implemented without changing existing applications</p></li></ul><p><strong>Handling of Schema Changes:</strong> </p><ul><li><p><strong>Event Sourcing:</strong> Challenging - requires careful event versioning</p></li><li><p><strong>Transactional Outbox:</strong> Moderate - affects outbox table and consumers</p></li><li><p><strong>Listen to Yourself:</strong> Moderate - affects event structure and consumers</p></li><li><p><strong>CDC:</strong> Challenging - changes in source database schema need to be carefully managed</p></li></ul><p><strong>Real-time Data Integration:</strong> </p><ul><li><p><strong>Event Sourcing:</strong> Excellent - events can be processed in real-time</p></li><li><p><strong>Transactional Outbox:</strong> Good - near real-time, depending on relay frequency</p></li><li><p><strong>Listen to Yourself:</strong> Excellent - events are processed immediately</p></li><li><p><strong>CDC:</strong> Very Good - near real-time, with minimal delay</p></li></ul><p><strong>Resilience to System Failures:</strong> </p><ul><li><p><strong>Event Sourcing:</strong> High - can rebuild state from event log</p></li><li><p><strong>Transactional Outbox:</strong> Good - messages persist in outbox until processed</p></li><li><p><strong>Listen to Yourself:</strong> Moderate - depends on message broker reliability</p></li><li><p><strong>CDC:</strong> Good - can resume from last processed transaction log position</p></li></ul><p><strong>Latency:</strong> </p><ul><li><p><strong>Event Sourcing:</strong> Can be high for complex queries on current state</p></li><li><p><strong>Transactional Outbox:</strong> Low for writes, potential delay in message processing</p></li><li><p><strong>Listen to Yourself:</strong> Moderate - additional network round-trip</p></li><li><p><strong>CDC:</strong> Low to Moderate - depends on CDC tool and configuration</p></li></ul>]]></content:encoded></item><item><title><![CDATA[Common microservice failures and how DoorDash mitigates them]]></title><description><![CDATA[On the different pitfalls that arise in distributed systems, what are some of the localised solutions, what can be done at a more global level and how DoorDash tries to mitigate their failures]]></description><link>https://blog.diana-enache.com/p/common-microservice-failures-and</link><guid isPermaLink="false">https://blog.diana-enache.com/p/common-microservice-failures-and</guid><dc:creator><![CDATA[Diana Darie]]></dc:creator><pubDate>Mon, 08 Jul 2024 07:18:04 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/1658362d-e60f-457a-821c-d93c3e3b887f_2406x1332.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a href="https://www.doordash.com/">DoorDash</a> is an on-demand food delivery service that connects customers with local restaurants through its app and website. It&#8217;s currently one of the largest food marketplaces in the US with almost <a href="https://backlinko.com/doordash-users">37 millions users</a>. The platform enables users to browse menus, place orders, and have meals delivered directly to their doorstep. </p><p>In 2020, with the constant increase in their user base, the team decided to move from a Django monolith to a microservice architecture. This allowed for better scalability options, shorter waits for tests completion, faster deployment times and increased developer velocity. They wrote a great <a href="https://doordash.engineering/2020/12/02/how-doordash-transitioned-from-a-monolith-to-microservices/?utm_source=blog.quastor.org&amp;utm_medium=newsletter&amp;utm_campaign=scaling-microservices-at-doordash">blog post</a> on how they managed the transition.  But this change also brought a lot of complexity with it.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2h0_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F875e9ff4-9802-4032-aecc-c4ba20b04154_2786x1435.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2h0_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F875e9ff4-9802-4032-aecc-c4ba20b04154_2786x1435.jpeg 424w, https://substackcdn.com/image/fetch/$s_!2h0_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F875e9ff4-9802-4032-aecc-c4ba20b04154_2786x1435.jpeg 848w, https://substackcdn.com/image/fetch/$s_!2h0_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F875e9ff4-9802-4032-aecc-c4ba20b04154_2786x1435.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!2h0_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F875e9ff4-9802-4032-aecc-c4ba20b04154_2786x1435.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2h0_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F875e9ff4-9802-4032-aecc-c4ba20b04154_2786x1435.jpeg" width="1456" height="750" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/875e9ff4-9802-4032-aecc-c4ba20b04154_2786x1435.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:750,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:171370,&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_!2h0_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F875e9ff4-9802-4032-aecc-c4ba20b04154_2786x1435.jpeg 424w, https://substackcdn.com/image/fetch/$s_!2h0_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F875e9ff4-9802-4032-aecc-c4ba20b04154_2786x1435.jpeg 848w, https://substackcdn.com/image/fetch/$s_!2h0_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F875e9ff4-9802-4032-aecc-c4ba20b04154_2786x1435.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!2h0_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F875e9ff4-9802-4032-aecc-c4ba20b04154_2786x1435.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">Courtesy of <a href="https://doordash.engineering/2020/12/02/how-doordash-transitioned-from-a-monolith-to-microservices/?utm_source=blog.quastor.org&amp;utm_medium=newsletter&amp;utm_campaign=scaling-microservices-at-doordash">DoorDash</a></figcaption></figure></div><p>The new architecture introduced other types of issues which we&#8217;re going to talk about in this article. We&#8217;re going to have a look at some of the common pitfalls and anti-patterns that appear in a microservice architecture, how Doordash solved them at a local level and how they&#8217;re attempting to mitigate them at a global level.</p><h3>Common pitfalls with microservice architectures</h3><p><strong>1. Cascading Failure - </strong>A cascading failure happens when the failure of one service leads to the failure of other dependent services. This can cause a chain reaction, potentially bringing down the entire system.</p><p>DoorDash had an outage of this kind that they talked about in this <a href="https://doordash.engineering/2022/05/13/doordashs-may-12th-outage/?utm_source=blog.quastor.org&amp;utm_medium=referral&amp;utm_campaign=scaling-microservices-at-doordash">blog post</a>. In their case, the chain of failure started from a seemingly innocuous database maintenance, which increased the database latency. The latency then bubbled up to the upstream services, causing errors from timeouts and resource exhaustion. The increased error rates triggered a misconfigured circuit breaker, which stopped traffic between a lot of unrelated services, resulting in an outage with a wide blast radius.</p><p><strong>Why it happens:</strong> </p><ul><li><p><strong>Tight Coupling</strong>: Services are too dependent on each other, leading to a domino effect.</p></li><li><p><strong>Lack of Isolation</strong>: Failures in one service are not contained and propagate to others.</p></li><li><p><strong>Resource Exhaustion</strong>: Failure in a critical service can lead to resource exhaustion (e.g., CPU, memory) in dependent services.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!HjW6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c1193b7-2753-42f1-a879-e06346b51437_4177x957.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!HjW6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c1193b7-2753-42f1-a879-e06346b51437_4177x957.jpeg 424w, https://substackcdn.com/image/fetch/$s_!HjW6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c1193b7-2753-42f1-a879-e06346b51437_4177x957.jpeg 848w, https://substackcdn.com/image/fetch/$s_!HjW6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c1193b7-2753-42f1-a879-e06346b51437_4177x957.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!HjW6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c1193b7-2753-42f1-a879-e06346b51437_4177x957.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!HjW6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c1193b7-2753-42f1-a879-e06346b51437_4177x957.jpeg" width="1456" height="334" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6c1193b7-2753-42f1-a879-e06346b51437_4177x957.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:334,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:162270,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!HjW6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c1193b7-2753-42f1-a879-e06346b51437_4177x957.jpeg 424w, https://substackcdn.com/image/fetch/$s_!HjW6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c1193b7-2753-42f1-a879-e06346b51437_4177x957.jpeg 848w, https://substackcdn.com/image/fetch/$s_!HjW6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c1193b7-2753-42f1-a879-e06346b51437_4177x957.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!HjW6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c1193b7-2753-42f1-a879-e06346b51437_4177x957.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">Diagram based on <a href="https://doordash.engineering/2023/03/14/failure-mitigation-for-microservices-an-intro-to-aperture/?utm_source=blog.quastor.org&amp;utm_medium=referral&amp;utm_campaign=scaling-microservices-at-doordash">DoorDash&#8217;s</a> illustrating a distributed system experiencing a cascading failure</figcaption></figure></div><p><strong>2.</strong> <strong>Retry Storm</strong> - A retry storm occurs when a service failure triggers multiple retries from dependent services, which can overwhelm the failing service even more. Retries can worsen the issue when the downstream services are unavailable or slow, leading to work amplification, as each failed request is retried multiple times, which can cause an already degraded service to deteriorate further.</p><p><strong>Why it happens:</strong> </p><ul><li><p><strong>Uncontrolled Retries</strong>: Services automatically retry failed requests without considering the state of the failing service.</p></li><li><p><strong>Lack of Backoff</strong>: Retries happen too frequently, without appropriate delay, exacerbating the problem.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mu4S!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6a52abf-e3a3-44ed-a31a-20cb7960a181_3510x1139.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mu4S!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6a52abf-e3a3-44ed-a31a-20cb7960a181_3510x1139.jpeg 424w, https://substackcdn.com/image/fetch/$s_!mu4S!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6a52abf-e3a3-44ed-a31a-20cb7960a181_3510x1139.jpeg 848w, https://substackcdn.com/image/fetch/$s_!mu4S!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6a52abf-e3a3-44ed-a31a-20cb7960a181_3510x1139.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!mu4S!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6a52abf-e3a3-44ed-a31a-20cb7960a181_3510x1139.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mu4S!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6a52abf-e3a3-44ed-a31a-20cb7960a181_3510x1139.jpeg" width="1456" height="472" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a6a52abf-e3a3-44ed-a31a-20cb7960a181_3510x1139.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:472,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:190516,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mu4S!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6a52abf-e3a3-44ed-a31a-20cb7960a181_3510x1139.jpeg 424w, https://substackcdn.com/image/fetch/$s_!mu4S!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6a52abf-e3a3-44ed-a31a-20cb7960a181_3510x1139.jpeg 848w, https://substackcdn.com/image/fetch/$s_!mu4S!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6a52abf-e3a3-44ed-a31a-20cb7960a181_3510x1139.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!mu4S!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6a52abf-e3a3-44ed-a31a-20cb7960a181_3510x1139.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Diagram based on <a href="https://doordash.engineering/2023/03/14/failure-mitigation-for-microservices-an-intro-to-aperture/?utm_source=blog.quastor.org&amp;utm_medium=referral&amp;utm_campaign=scaling-microservices-at-doordash">DoorDash&#8217;s</a> illustrating how a retry storm spreads in a system. The issue earlier that started with the db latency, spreads to the RPC calls and triggers retries in service 2, 3 and 5 which increase the load on the db even more.</figcaption></figure></div><p><strong>3. Death Spiral</strong> - A death spiral happens when the system starts to fail under load, and the attempts to handle the failure (like retries or additional resource allocation) further degrade the system&#8217;s performance, leading to a vicious cycle of deteriorating performance.</p><p>We&#8217;ve seen earlier how issues can spread vertically through different services dependant on one another. But they can also spread horizontally, inside the service cluster, from one node to another.</p><p><strong>Why this happens:</strong> </p><ul><li><p><strong>Resource Contention</strong>: Excessive retries and fallback operations consume more resources, reducing availability for normal operations.</p></li><li><p><strong>Unbalanced Load</strong>: Efforts to handle failures, like adding more instances, might lead to other parts of the system becoming overloaded.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!jEB-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F920dbb1f-33c6-42c2-ace1-344c6503e53b_3000x1333.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jEB-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F920dbb1f-33c6-42c2-ace1-344c6503e53b_3000x1333.jpeg 424w, https://substackcdn.com/image/fetch/$s_!jEB-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F920dbb1f-33c6-42c2-ace1-344c6503e53b_3000x1333.jpeg 848w, https://substackcdn.com/image/fetch/$s_!jEB-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F920dbb1f-33c6-42c2-ace1-344c6503e53b_3000x1333.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!jEB-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F920dbb1f-33c6-42c2-ace1-344c6503e53b_3000x1333.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jEB-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F920dbb1f-33c6-42c2-ace1-344c6503e53b_3000x1333.jpeg" width="1456" height="647" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/920dbb1f-33c6-42c2-ace1-344c6503e53b_3000x1333.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:647,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:166761,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!jEB-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F920dbb1f-33c6-42c2-ace1-344c6503e53b_3000x1333.jpeg 424w, https://substackcdn.com/image/fetch/$s_!jEB-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F920dbb1f-33c6-42c2-ace1-344c6503e53b_3000x1333.jpeg 848w, https://substackcdn.com/image/fetch/$s_!jEB-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F920dbb1f-33c6-42c2-ace1-344c6503e53b_3000x1333.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!jEB-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F920dbb1f-33c6-42c2-ace1-344c6503e53b_3000x1333.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Diagram based on <a href="https://doordash.engineering/2023/03/14/failure-mitigation-for-microservices-an-intro-to-aperture/?utm_source=blog.quastor.org&amp;utm_medium=referral&amp;utm_campaign=scaling-microservices-at-doordash">DoorDash&#8217;s</a> illustrating a service running on 3 nodes. 2 nodes go down due to some network issue so the incoming requests get routed to the only other available node left. This causes significantly higher resource utilisation which leads to the remaining node to crash due to resource saturation.</figcaption></figure></div><p><strong>4. Metastable Failure</strong> - Metastable failure refers to a state where the system appears to be stable under low load but becomes unstable and fails when the load increases beyond a certain threshold. <a href="https://sigops.org/s/conferences/hotos/2021/papers/hotos21-s11-bronson.pdf">Metastable failures occur in open systems with an uncontrolled source of load where a trigger causes the system to enter a bad state that persists even when the trigger is removed.</a> When any of several potential triggers cause the system to enter a metastable state, a feedback loop sustains the failure, keeping the system in this state until a significant (usually manual) corrective action is applied.</p><p>For example, an initial trigger such as a surge in users, might cause one of the backend services to load shed and start responding to certain requests with 429 (rate limit). The callers will then retry their calls, but these retries, combined with requests from new users, overwhelm the backend service even more, leading to further load shedding. This results in a positive feedback loop where calls are continuously retried (along with new calls), get rate limited, and then retried again, perpetuating the cycle.</p><p>The above is called a <strong>Thundering Herd problem</strong> and is one example of a Metastable failure.</p><p><strong>Why this happens:</strong> </p><ul><li><p><strong>Insufficient Capacity</strong>: The system is not designed to handle peak loads, leading to instability.</p></li><li><p><strong>Hidden Bottlenecks</strong>: Bottlenecks that are not apparent under normal conditions become critical under high load.</p></li><li><p><strong>Latency Sensitivity</strong>: Small increases in latency can have a disproportionate effect on the system's stability.</p></li><li><p><strong>Request Retries</strong>: Retrying failed requests is widely used to mask transient issues. However, it also results in work amplification, which can lead to additional failures</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8KA5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61e5fdbb-000d-4fdb-ac7e-7825ae7201dd_2902x1378.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8KA5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61e5fdbb-000d-4fdb-ac7e-7825ae7201dd_2902x1378.jpeg 424w, https://substackcdn.com/image/fetch/$s_!8KA5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61e5fdbb-000d-4fdb-ac7e-7825ae7201dd_2902x1378.jpeg 848w, https://substackcdn.com/image/fetch/$s_!8KA5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61e5fdbb-000d-4fdb-ac7e-7825ae7201dd_2902x1378.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!8KA5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61e5fdbb-000d-4fdb-ac7e-7825ae7201dd_2902x1378.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8KA5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61e5fdbb-000d-4fdb-ac7e-7825ae7201dd_2902x1378.jpeg" width="590" height="280.00686813186815" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/61e5fdbb-000d-4fdb-ac7e-7825ae7201dd_2902x1378.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:691,&quot;width&quot;:1456,&quot;resizeWidth&quot;:590,&quot;bytes&quot;:128827,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!8KA5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61e5fdbb-000d-4fdb-ac7e-7825ae7201dd_2902x1378.jpeg 424w, https://substackcdn.com/image/fetch/$s_!8KA5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61e5fdbb-000d-4fdb-ac7e-7825ae7201dd_2902x1378.jpeg 848w, https://substackcdn.com/image/fetch/$s_!8KA5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61e5fdbb-000d-4fdb-ac7e-7825ae7201dd_2902x1378.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!8KA5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61e5fdbb-000d-4fdb-ac7e-7825ae7201dd_2902x1378.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Lifecycle of a metastable failure</figcaption></figure></div><h3>Solutions at a local level</h3><p>There are a couple of known techniques which are used to solve the above, some of which are being used by DoorDash as well:</p><ul><li><p><strong>Exponential Backoff</strong> - by gradually increasing the delay between retries to reduce the load</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!opIm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F411aa263-bd7d-4635-85aa-decef5022f1f_3730x1072.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!opIm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F411aa263-bd7d-4635-85aa-decef5022f1f_3730x1072.jpeg 424w, https://substackcdn.com/image/fetch/$s_!opIm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F411aa263-bd7d-4635-85aa-decef5022f1f_3730x1072.jpeg 848w, https://substackcdn.com/image/fetch/$s_!opIm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F411aa263-bd7d-4635-85aa-decef5022f1f_3730x1072.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!opIm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F411aa263-bd7d-4635-85aa-decef5022f1f_3730x1072.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!opIm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F411aa263-bd7d-4635-85aa-decef5022f1f_3730x1072.jpeg" width="660" height="189.47802197802199" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/411aa263-bd7d-4635-85aa-decef5022f1f_3730x1072.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:418,&quot;width&quot;:1456,&quot;resizeWidth&quot;:660,&quot;bytes&quot;:84641,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!opIm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F411aa263-bd7d-4635-85aa-decef5022f1f_3730x1072.jpeg 424w, https://substackcdn.com/image/fetch/$s_!opIm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F411aa263-bd7d-4635-85aa-decef5022f1f_3730x1072.jpeg 848w, https://substackcdn.com/image/fetch/$s_!opIm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F411aa263-bd7d-4635-85aa-decef5022f1f_3730x1072.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!opIm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F411aa263-bd7d-4635-85aa-decef5022f1f_3730x1072.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><ul><li><p><strong>Retry Limits</strong> - by setting a maximum limit on the number of retries to prevent endless retry loops.</p></li><li><p><strong>Circuit Breakers - </strong>by activating and reducing the number of calls a dependent service makes to another one. Some examples of how circuit breakers are used by other companies:</p><ul><li><p><strong><a href="https://github.com/Netflix/Hystrix">Netflix's Hystrix library</a></strong>: Netflix developed Hystrix as a library to manage failures within their distributed system. When Hystrix identifies that a remote service is down or unresponsive, it activates the circuit breaker, stopping further requests from being sent to the problematic service. It can also offer alternative responses or retry the request after a designated period.</p></li><li><p><strong><a href="https://aws.amazon.com/blogs/containers/announcing-amazon-ecs-deployment-circuit-breaker/">AWS ECS</a></strong>: ECS employs a circuit breaker pattern to automatically isolate failing services, thus preventing cascading failures within applications. This pattern also reduces latency and resource consumption during recovery from a service failure. It effectively ensures high availability and reliability for containerized applications.</p></li><li><p><strong><a href="https://developers.soundcloud.com/blog/lessons-in-resilience-at-SoundCloud">SoundCloud</a></strong>: SoundCloud also uses circuit breaker to handle failures in their distributed architecture.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fEC-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45d1785c-d125-48be-a171-d841a7cb4b6f_3518x1136.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fEC-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45d1785c-d125-48be-a171-d841a7cb4b6f_3518x1136.jpeg 424w, https://substackcdn.com/image/fetch/$s_!fEC-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45d1785c-d125-48be-a171-d841a7cb4b6f_3518x1136.jpeg 848w, https://substackcdn.com/image/fetch/$s_!fEC-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45d1785c-d125-48be-a171-d841a7cb4b6f_3518x1136.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!fEC-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45d1785c-d125-48be-a171-d841a7cb4b6f_3518x1136.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fEC-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45d1785c-d125-48be-a171-d841a7cb4b6f_3518x1136.jpeg" width="1456" height="470" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/45d1785c-d125-48be-a171-d841a7cb4b6f_3518x1136.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:470,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:114651,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!fEC-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45d1785c-d125-48be-a171-d841a7cb4b6f_3518x1136.jpeg 424w, https://substackcdn.com/image/fetch/$s_!fEC-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45d1785c-d125-48be-a171-d841a7cb4b6f_3518x1136.jpeg 848w, https://substackcdn.com/image/fetch/$s_!fEC-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45d1785c-d125-48be-a171-d841a7cb4b6f_3518x1136.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!fEC-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45d1785c-d125-48be-a171-d841a7cb4b6f_3518x1136.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div></li></ul><ul><li><p><strong>Bulkheads</strong> - by isolating critical resources (like thread pools, database connections, or service instances) ensuring that failures or high resource usage in one microservice do not impact others sharing the same resources.</p></li><li><p><strong>Timeouts &amp; Fallbacks</strong> - by defining the maximum acceptable duration for a microservice to respond to a request and preventing indefinite waiting and and resource consumption when a service is slow or unresponsive. </p></li><li><p><strong>Load Shedding</strong> - by prioritising and limiting incoming requests to prevent overload.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!E0X4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fd230cd-18e6-4dbd-af20-1d960055a423_3401x1175.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!E0X4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fd230cd-18e6-4dbd-af20-1d960055a423_3401x1175.jpeg 424w, https://substackcdn.com/image/fetch/$s_!E0X4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fd230cd-18e6-4dbd-af20-1d960055a423_3401x1175.jpeg 848w, https://substackcdn.com/image/fetch/$s_!E0X4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fd230cd-18e6-4dbd-af20-1d960055a423_3401x1175.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!E0X4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fd230cd-18e6-4dbd-af20-1d960055a423_3401x1175.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!E0X4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fd230cd-18e6-4dbd-af20-1d960055a423_3401x1175.jpeg" width="616" height="212.80769230769232" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5fd230cd-18e6-4dbd-af20-1d960055a423_3401x1175.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:503,&quot;width&quot;:1456,&quot;resizeWidth&quot;:616,&quot;bytes&quot;:107957,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!E0X4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fd230cd-18e6-4dbd-af20-1d960055a423_3401x1175.jpeg 424w, https://substackcdn.com/image/fetch/$s_!E0X4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fd230cd-18e6-4dbd-af20-1d960055a423_3401x1175.jpeg 848w, https://substackcdn.com/image/fetch/$s_!E0X4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fd230cd-18e6-4dbd-af20-1d960055a423_3401x1175.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!E0X4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fd230cd-18e6-4dbd-af20-1d960055a423_3401x1175.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><ul><li><p><strong>Graceful Degradation</strong> - by minimising the amount of work that needs to be done, degrading non-essential functionalities or reduce service levels during times of high load, resource scarcity, or service unavailability. This can be achieved by determining essential functionalities that must remain operational even under degraded conditions, simplifying non-critical features to prioritise core functionalities and implementing fallback strategies to maintain basic service levels when primary functionalities are unavailable.</p></li><li><p><strong>Capacity Planning</strong> - by analysing historical data, user patterns, and trends to forecast future demand for each microservice and determining the scalability requirements based on expected growth, seasonal fluctuations, and special events.</p></li></ul><h3>Shortcomings of the local countermeasures</h3><p>The current localised mechanisms face similar limitations:</p><ul><li><p>They rely on <strong>metrics specific to the individual service</strong> to determine its health. However, many types of failures involve interactions across multiple components, requiring a comprehensive system-wide perspective to effectively address overload conditions.</p></li><li><p>They use <strong>general metrics and heuristics</strong> to assess the system health, which may lack precision. For instance, high latency alone may not indicate service overload; it could stem from slow downstream services.</p></li><li><p>Their corrective actions are <strong>constrained</strong>. Operating within the local service, these mechanisms can only take local actions which may not be optimal for restoring the system health, as the root cause of the issue might lie elsewhere.</p></li></ul><h3>Solutions at a global level</h3><p>One limitation of load shedding, circuit breakers, and graceful degradation is their narrow perspective within the system. These tools assess factors like their own resource usage, immediate dependencies, and incoming request volume. However, they lack the ability to adopt a global view of the entire system and decide based on that.</p><p><a href="https://github.com/fluxninja/aperture">Aperture</a>, an open-source system for reliability management, goes beyond local solutions by implementing a centralised load control. It provides a unified system for managing loads across multiple services during outages. It has 3 main components:</p><ul><li><p><strong>Observe</strong>: Aperture gathers reliability metrics from each node and consolidates them using Prometheus.</p></li><li><p><strong>Analyse</strong>: A standalone Aperture controller continuously monitors these metrics and detects deviations from Service Level Objectives (SLOs).</p></li><li><p><strong>Actuate</strong>: Upon detecting anomalies, the Aperture controller triggers policies tailored to observed patterns and applies actions on each node, such as load shedding or distributed rate limiting.</p></li></ul><p>Aperture utilizes YAML-based policies that guides its actions during system disruptions. When an alert is triggered, Aperture automatically executes actions based on these configured policies. Some of the actions it offers include distributed rate limiting and concurrency control (also known as load shedding). By maintaining a centralized oversight and control of the entire system, Aperture enables various strategies to mitigate outages. For instance, it can be configured to implement a policy that throttles traffic to an upstream service when a downstream service is overwhelmed, preventing excessive requests from reaching the problematic area and thereby enhancing system responsiveness and cost-efficiency.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3dQx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe836a95a-9dfb-4fb2-8301-05efcb479947_2026x1140.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3dQx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe836a95a-9dfb-4fb2-8301-05efcb479947_2026x1140.png 424w, https://substackcdn.com/image/fetch/$s_!3dQx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe836a95a-9dfb-4fb2-8301-05efcb479947_2026x1140.png 848w, https://substackcdn.com/image/fetch/$s_!3dQx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe836a95a-9dfb-4fb2-8301-05efcb479947_2026x1140.png 1272w, https://substackcdn.com/image/fetch/$s_!3dQx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe836a95a-9dfb-4fb2-8301-05efcb479947_2026x1140.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3dQx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe836a95a-9dfb-4fb2-8301-05efcb479947_2026x1140.png" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e836a95a-9dfb-4fb2-8301-05efcb479947_2026x1140.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;:1124119,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!3dQx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe836a95a-9dfb-4fb2-8301-05efcb479947_2026x1140.png 424w, https://substackcdn.com/image/fetch/$s_!3dQx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe836a95a-9dfb-4fb2-8301-05efcb479947_2026x1140.png 848w, https://substackcdn.com/image/fetch/$s_!3dQx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe836a95a-9dfb-4fb2-8301-05efcb479947_2026x1140.png 1272w, https://substackcdn.com/image/fetch/$s_!3dQx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe836a95a-9dfb-4fb2-8301-05efcb479947_2026x1140.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Example of a policy for a load scheduler as shown in the <strong><a href="https://www.youtube.com/watch?v=ws9__JjaJsE&amp;ab_channel=USENIX">SREcon23 Asia/Pacific</a> </strong>talk</figcaption></figure></div><p><a href="https://doordash.engineering/2023/03/14/failure-mitigation-for-microservices-an-intro-to-aperture/?utm_source=blog.quastor.org&amp;utm_medium=referral&amp;utm_campaign=scaling-microservices-at-doordash">DoorDash</a> deployed Aperture within one of their core services and conducted artificial request simulations to evaluate its performance. They discovered that Aperture effectively operated as a robust and user-friendly global rate limiter and load shedding solution, providing a <a href="https://docs.fluxninja.com/reference/policies/bundled-blueprints/policies/latency-aimd-concurrency-limiting">concurrency limiting algorithm</a> which minimises the impact of unexpected load or latency.</p><p>The Aperture blog also provides good use cases of how their solution can be used to solve production problems: </p><ul><li><p><a href="https://blog.fluxninja.com/blog/protecting-postgresql-with-adaptive-rate-limiting">Protecting PostgreSQL with Adaptive Rate Limiting</a></p></li><li><p><a href="https://blog.fluxninja.com/blog/concurrency-scheduling-in-mistral-ai">Balancing Cost and Efficiency in Mistral with Concurrency Scheduling</a></p></li><li><p><a href="https://blog.fluxninja.com/blog/coderabbit-openai-rate-limits">Squeezing Water from Stone: Managing OpenAI Rate Limits with Request Prioritization</a></p></li></ul><h3>Conclusion</h3><p>We had a look into the different pitfalls that arise in distributed systems, what are the triggers that might cause them, what are some of the localised solutions to prevent them from happening and what can be done at a more global level.</p><p>In the next articles, we&#8217;re going to take a deeper look into how Aperture works, how we can configure it and how to define a set of policies for a given use case. </p>]]></content:encoded></item><item><title><![CDATA[From Pixels to Information: A Comprehensive Guide on QR Codes]]></title><description><![CDATA[On what QR codes are, why do we use them, and how do we encode/decode information through them]]></description><link>https://blog.diana-enache.com/p/from-pixels-to-information-a-comprehensive</link><guid isPermaLink="false">https://blog.diana-enache.com/p/from-pixels-to-information-a-comprehensive</guid><dc:creator><![CDATA[Diana Darie]]></dc:creator><pubDate>Fri, 05 Apr 2024 15:37:11 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/9037d9a9-ef24-40b8-9e2c-14ad1d2869dc_1936x1008.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You&#8217;ve probably scanned a QR code before. They&#8217;re everywhere. But have you wondered how they work? Because this has been on my mind a lot recently. So I did some investigation and here is a summary of the key findings, notable points and fun facts.</p><p><strong>How and why QR codes came into being</strong></p><p>Masahiro Hara, a Japanese engineer who worked at Denso Wave then, invented the <strong>QR Code</strong> (or <strong>Quick Response codes</strong>) in 1994 to meet the need for a more efficient and versatile method of tracking automotive parts during manufacturing. Hara and his team developed QR codes as an improvement over traditional barcodes. </p><p><strong>QR Codes vs Barcodes</strong></p><p>Traditional barcodes could only store a limited amount of information horizontally, while QR codes can store much more data both horizontally and vertically. A barcode can store 1,556 bytes, whereas a QR Code can store up to 7,089 numeric characters, 4,296 alphanumeric characters, 2,953 bytes, and 1,817 kanji characters.</p><h1>Components</h1><p>And now let&#8217;s get into the fun part, what do all those black and white squares represent?  QR Codes consist of black and white elements called <strong>modules</strong>, where black represents 1 and white 0. These modules can be combined into meaningful binary messages.  </p><p>Before diving into how we encode/decode the information, let&#8217;s first analyse what the main components of the QR code are:</p><p><strong>Function Patterns</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!79Lu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6db2a228-291f-49df-9f22-888a8a936b01_1994x604.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!79Lu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6db2a228-291f-49df-9f22-888a8a936b01_1994x604.png 424w, https://substackcdn.com/image/fetch/$s_!79Lu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6db2a228-291f-49df-9f22-888a8a936b01_1994x604.png 848w, https://substackcdn.com/image/fetch/$s_!79Lu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6db2a228-291f-49df-9f22-888a8a936b01_1994x604.png 1272w, https://substackcdn.com/image/fetch/$s_!79Lu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6db2a228-291f-49df-9f22-888a8a936b01_1994x604.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!79Lu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6db2a228-291f-49df-9f22-888a8a936b01_1994x604.png" width="1456" height="441" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6db2a228-291f-49df-9f22-888a8a936b01_1994x604.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:441,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:124356,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!79Lu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6db2a228-291f-49df-9f22-888a8a936b01_1994x604.png 424w, https://substackcdn.com/image/fetch/$s_!79Lu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6db2a228-291f-49df-9f22-888a8a936b01_1994x604.png 848w, https://substackcdn.com/image/fetch/$s_!79Lu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6db2a228-291f-49df-9f22-888a8a936b01_1994x604.png 1272w, https://substackcdn.com/image/fetch/$s_!79Lu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6db2a228-291f-49df-9f22-888a8a936b01_1994x604.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><ol><li><p><strong>Quiet Zone</strong> - helps the scanner to distinguish between the QR code and its surroundings, making it easier to detect the QR Code.</p></li><li><p><strong>Position Pattern</strong> - located in 3 of the QR code&#8217;s corners, it allows the scanner to quickly recognise the code orientation. This means the code can be scanned at any angle. </p></li><li><p><strong>Separator</strong> - used to keep space between the position pattern and the other information, helping the scanner to identify the position pattern.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dyK3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36e6f2e5-abdc-4b6a-aa5d-74588b9d3d20_1910x534.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dyK3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36e6f2e5-abdc-4b6a-aa5d-74588b9d3d20_1910x534.png 424w, https://substackcdn.com/image/fetch/$s_!dyK3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36e6f2e5-abdc-4b6a-aa5d-74588b9d3d20_1910x534.png 848w, https://substackcdn.com/image/fetch/$s_!dyK3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36e6f2e5-abdc-4b6a-aa5d-74588b9d3d20_1910x534.png 1272w, https://substackcdn.com/image/fetch/$s_!dyK3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36e6f2e5-abdc-4b6a-aa5d-74588b9d3d20_1910x534.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dyK3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36e6f2e5-abdc-4b6a-aa5d-74588b9d3d20_1910x534.png" width="1456" height="407" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/36e6f2e5-abdc-4b6a-aa5d-74588b9d3d20_1910x534.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:407,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:94414,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!dyK3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36e6f2e5-abdc-4b6a-aa5d-74588b9d3d20_1910x534.png 424w, https://substackcdn.com/image/fetch/$s_!dyK3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36e6f2e5-abdc-4b6a-aa5d-74588b9d3d20_1910x534.png 848w, https://substackcdn.com/image/fetch/$s_!dyK3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36e6f2e5-abdc-4b6a-aa5d-74588b9d3d20_1910x534.png 1272w, https://substackcdn.com/image/fetch/$s_!dyK3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36e6f2e5-abdc-4b6a-aa5d-74588b9d3d20_1910x534.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></li><li><p><strong>Alignment Pattern</strong> - used for correcting distortion by straightening the code on a curved surface. On higher versions, QR codes tend to have more alignment patterns. Ver40 which is the largest QR code consists of 46 alignment patterns. Ver1 doesn&#8217;t require any alignment patterns.</p></li><li><p><strong>Timing Pattern</strong> - helps the scanner to determine the width of a single module.</p></li></ol><p><strong>Encoding Region</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!IZBr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F318b5273-56dc-4c08-8a1d-c8e7a74d920e_1726x532.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IZBr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F318b5273-56dc-4c08-8a1d-c8e7a74d920e_1726x532.png 424w, https://substackcdn.com/image/fetch/$s_!IZBr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F318b5273-56dc-4c08-8a1d-c8e7a74d920e_1726x532.png 848w, https://substackcdn.com/image/fetch/$s_!IZBr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F318b5273-56dc-4c08-8a1d-c8e7a74d920e_1726x532.png 1272w, https://substackcdn.com/image/fetch/$s_!IZBr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F318b5273-56dc-4c08-8a1d-c8e7a74d920e_1726x532.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!IZBr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F318b5273-56dc-4c08-8a1d-c8e7a74d920e_1726x532.png" width="1456" height="449" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/318b5273-56dc-4c08-8a1d-c8e7a74d920e_1726x532.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:449,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:98595,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!IZBr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F318b5273-56dc-4c08-8a1d-c8e7a74d920e_1726x532.png 424w, https://substackcdn.com/image/fetch/$s_!IZBr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F318b5273-56dc-4c08-8a1d-c8e7a74d920e_1726x532.png 848w, https://substackcdn.com/image/fetch/$s_!IZBr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F318b5273-56dc-4c08-8a1d-c8e7a74d920e_1726x532.png 1272w, https://substackcdn.com/image/fetch/$s_!IZBr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F318b5273-56dc-4c08-8a1d-c8e7a74d920e_1726x532.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><ol><li><p><strong>Version Information</strong> -  there are 40 versions of QR codes, from 1 up to 40; this region specifies which version is being used.</p></li><li><p><strong>Format Information</strong> - contains information such as error correction level, mask pattern etc.</p></li><li><p><strong>Data and error correction keys</strong> - the remaining available code is used for storing the data along with the error correction data. The correction data is done by the Reed-Solomon codes which allows the QR code to still be scanned if some information is corrupted/not visible etc. </p></li></ol><p>Putting everything together:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!AqV5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70e35dcd-afbc-4668-b7f1-6c4c9b6725f8_2008x1116.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!AqV5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70e35dcd-afbc-4668-b7f1-6c4c9b6725f8_2008x1116.png 424w, https://substackcdn.com/image/fetch/$s_!AqV5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70e35dcd-afbc-4668-b7f1-6c4c9b6725f8_2008x1116.png 848w, https://substackcdn.com/image/fetch/$s_!AqV5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70e35dcd-afbc-4668-b7f1-6c4c9b6725f8_2008x1116.png 1272w, https://substackcdn.com/image/fetch/$s_!AqV5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70e35dcd-afbc-4668-b7f1-6c4c9b6725f8_2008x1116.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!AqV5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70e35dcd-afbc-4668-b7f1-6c4c9b6725f8_2008x1116.png" width="1456" height="809" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/70e35dcd-afbc-4668-b7f1-6c4c9b6725f8_2008x1116.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:809,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:219623,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!AqV5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70e35dcd-afbc-4668-b7f1-6c4c9b6725f8_2008x1116.png 424w, https://substackcdn.com/image/fetch/$s_!AqV5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70e35dcd-afbc-4668-b7f1-6c4c9b6725f8_2008x1116.png 848w, https://substackcdn.com/image/fetch/$s_!AqV5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70e35dcd-afbc-4668-b7f1-6c4c9b6725f8_2008x1116.png 1272w, https://substackcdn.com/image/fetch/$s_!AqV5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70e35dcd-afbc-4668-b7f1-6c4c9b6725f8_2008x1116.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><h1>How does versioning work?</h1><p>There are <strong>40 versions</strong> of the conventional QR code. Each version has a different number of data modules, commencing with Version 1 (21 &#215; 21 modules) up to Version 40 (177 &#215; 177 modules). </p><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/IysLC/1/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e2947fe2-46f9-4c50-8134-488c722c1fe9_1260x660.png&quot;,&quot;thumbnail_url_full&quot;:&quot;&quot;,&quot;height&quot;:283,&quot;title&quot;:&quot;QR Code Versioning&quot;,&quot;description&quot;:&quot;&quot;}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/IysLC/1/" width="730" height="283" frameborder="0" scrolling="no"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><p>With a new higher version, another 4 additional modules per side are added.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0A-3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51ffa78d-c310-48e8-bcf1-7df81bfb3975_1886x1016.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0A-3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51ffa78d-c310-48e8-bcf1-7df81bfb3975_1886x1016.png 424w, https://substackcdn.com/image/fetch/$s_!0A-3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51ffa78d-c310-48e8-bcf1-7df81bfb3975_1886x1016.png 848w, https://substackcdn.com/image/fetch/$s_!0A-3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51ffa78d-c310-48e8-bcf1-7df81bfb3975_1886x1016.png 1272w, https://substackcdn.com/image/fetch/$s_!0A-3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51ffa78d-c310-48e8-bcf1-7df81bfb3975_1886x1016.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0A-3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51ffa78d-c310-48e8-bcf1-7df81bfb3975_1886x1016.png" width="1456" height="784" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/51ffa78d-c310-48e8-bcf1-7df81bfb3975_1886x1016.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:784,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:210370,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!0A-3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51ffa78d-c310-48e8-bcf1-7df81bfb3975_1886x1016.png 424w, https://substackcdn.com/image/fetch/$s_!0A-3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51ffa78d-c310-48e8-bcf1-7df81bfb3975_1886x1016.png 848w, https://substackcdn.com/image/fetch/$s_!0A-3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51ffa78d-c310-48e8-bcf1-7df81bfb3975_1886x1016.png 1272w, https://substackcdn.com/image/fetch/$s_!0A-3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51ffa78d-c310-48e8-bcf1-7df81bfb3975_1886x1016.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The higher the version, the higher the number of modules</figcaption></figure></div><p><strong>How would we know which version we need to use? </strong></p><p><a href="https://www.qrcode.com/en/about/version.html">QRCode.com</a> provides a comprehensive list of versions given the type of input data you want to use (numeric, alphanumeric, binary, kanji) and the correction level. </p><p>Let&#8217;s say I want to create a QR Code for the text &#8220;The Crafty Dev&#8220; which means we&#8217;re only interested in a 14 letter alphanumeric input. And let&#8217;s suppose we&#8217;re going to stick the QR code in various places outside, so we need a pretty high error correction capability (in case it rains or it gets stained etc). We need to find a figure in the QRCode versioning table, that is 14 or over and with an H correction level, so a good version for us to use would be version 2.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ebeM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ce96fa0-70d4-4d36-9820-127c617f7401_1474x998.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ebeM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ce96fa0-70d4-4d36-9820-127c617f7401_1474x998.png 424w, https://substackcdn.com/image/fetch/$s_!ebeM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ce96fa0-70d4-4d36-9820-127c617f7401_1474x998.png 848w, https://substackcdn.com/image/fetch/$s_!ebeM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ce96fa0-70d4-4d36-9820-127c617f7401_1474x998.png 1272w, https://substackcdn.com/image/fetch/$s_!ebeM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ce96fa0-70d4-4d36-9820-127c617f7401_1474x998.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ebeM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ce96fa0-70d4-4d36-9820-127c617f7401_1474x998.png" width="636" height="430.6978021978022" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8ce96fa0-70d4-4d36-9820-127c617f7401_1474x998.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:986,&quot;width&quot;:1456,&quot;resizeWidth&quot;:636,&quot;bytes&quot;:221094,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ebeM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ce96fa0-70d4-4d36-9820-127c617f7401_1474x998.png 424w, https://substackcdn.com/image/fetch/$s_!ebeM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ce96fa0-70d4-4d36-9820-127c617f7401_1474x998.png 848w, https://substackcdn.com/image/fetch/$s_!ebeM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ce96fa0-70d4-4d36-9820-127c617f7401_1474x998.png 1272w, https://substackcdn.com/image/fetch/$s_!ebeM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ce96fa0-70d4-4d36-9820-127c617f7401_1474x998.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Finding the QR Code version we can use for encoding the text &#8220;The Crafty Dev&#8220;</figcaption></figure></div><h1>The Error Correction Level</h1><p>The QR code error correction is based on the Reed-Solomon algorithm which works in a similar way to the parity error correction - it adds extra bits to the data so that errors can be corrected.</p><blockquote><p><strong>Fun Fact</strong></p><p>The Voyager spacecraft uses the Reed-Solomon error correction to ensure that data transmitted from the outer reaches of the solar system can be reconstructed even if it encounters interference, which is highly probable. Given that signals from Voyager 1 can take up to 20 hours to reach Earth, employing an ARQ (Automatic Repeat reQuest) mechanism to request retransmission in case of errors would be highly impractical. (<a href="https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction#:~:text=In%201977%2C%20Reed%E2%80%93Solomon%20codes,Reed%E2%80%93Solomon%20codes%20are%20used.">source</a>)</p></blockquote><p>The way Reed-Solomon does encoding deserves a completely different article so I&#8217;ll link it here once it&#8217;s published, so stay tuned.</p><h1>Unmasking</h1><p>Now comes the crazy part. Let&#8217;s say we have a QR code and we want to manually decode it. Where do we start? The first thing we&#8217;ll need to look at is the Format Information section.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!onjw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3153a3c-e662-40db-97df-624052fb8fcf_1654x1032.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!onjw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3153a3c-e662-40db-97df-624052fb8fcf_1654x1032.png 424w, https://substackcdn.com/image/fetch/$s_!onjw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3153a3c-e662-40db-97df-624052fb8fcf_1654x1032.png 848w, https://substackcdn.com/image/fetch/$s_!onjw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3153a3c-e662-40db-97df-624052fb8fcf_1654x1032.png 1272w, https://substackcdn.com/image/fetch/$s_!onjw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3153a3c-e662-40db-97df-624052fb8fcf_1654x1032.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!onjw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3153a3c-e662-40db-97df-624052fb8fcf_1654x1032.png" width="574" height="357.96153846153845" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f3153a3c-e662-40db-97df-624052fb8fcf_1654x1032.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:908,&quot;width&quot;:1456,&quot;resizeWidth&quot;:574,&quot;bytes&quot;:163041,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!onjw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3153a3c-e662-40db-97df-624052fb8fcf_1654x1032.png 424w, https://substackcdn.com/image/fetch/$s_!onjw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3153a3c-e662-40db-97df-624052fb8fcf_1654x1032.png 848w, https://substackcdn.com/image/fetch/$s_!onjw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3153a3c-e662-40db-97df-624052fb8fcf_1654x1032.png 1272w, https://substackcdn.com/image/fetch/$s_!onjw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3153a3c-e662-40db-97df-624052fb8fcf_1654x1032.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The first 2 modules (colored red in the picture above) will give you the error correction level. And the next 3 (colored green) will give you the mask pattern.</p><p>This means we have a <strong>00</strong> error correction level, which means high, 30% of data bytes can be restored; and a <strong>111</strong> masking pattern. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dGTv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8687091-250e-48fb-99b0-7870a399922f_1640x788.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dGTv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8687091-250e-48fb-99b0-7870a399922f_1640x788.png 424w, https://substackcdn.com/image/fetch/$s_!dGTv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8687091-250e-48fb-99b0-7870a399922f_1640x788.png 848w, https://substackcdn.com/image/fetch/$s_!dGTv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8687091-250e-48fb-99b0-7870a399922f_1640x788.png 1272w, https://substackcdn.com/image/fetch/$s_!dGTv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8687091-250e-48fb-99b0-7870a399922f_1640x788.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dGTv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8687091-250e-48fb-99b0-7870a399922f_1640x788.png" width="1456" height="700" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e8687091-250e-48fb-99b0-7870a399922f_1640x788.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:700,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:257246,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!dGTv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8687091-250e-48fb-99b0-7870a399922f_1640x788.png 424w, https://substackcdn.com/image/fetch/$s_!dGTv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8687091-250e-48fb-99b0-7870a399922f_1640x788.png 848w, https://substackcdn.com/image/fetch/$s_!dGTv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8687091-250e-48fb-99b0-7870a399922f_1640x788.png 1272w, https://substackcdn.com/image/fetch/$s_!dGTv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8687091-250e-48fb-99b0-7870a399922f_1640x788.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The QR codes are usually masked, so we&#8217;ll have to take off the mask first. We put the coordinates of the current bit into the formula, and if the result is 0, we use the opposite bit of that. After removing the mask on the original QR code, we&#8217;ll get the following unmasked QR code:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bl1x!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe566cca1-b67f-4902-9bf9-f0a8e2caf52a_1864x674.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bl1x!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe566cca1-b67f-4902-9bf9-f0a8e2caf52a_1864x674.png 424w, https://substackcdn.com/image/fetch/$s_!bl1x!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe566cca1-b67f-4902-9bf9-f0a8e2caf52a_1864x674.png 848w, https://substackcdn.com/image/fetch/$s_!bl1x!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe566cca1-b67f-4902-9bf9-f0a8e2caf52a_1864x674.png 1272w, https://substackcdn.com/image/fetch/$s_!bl1x!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe566cca1-b67f-4902-9bf9-f0a8e2caf52a_1864x674.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bl1x!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe566cca1-b67f-4902-9bf9-f0a8e2caf52a_1864x674.png" width="1456" height="526" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e566cca1-b67f-4902-9bf9-f0a8e2caf52a_1864x674.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:526,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:175182,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!bl1x!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe566cca1-b67f-4902-9bf9-f0a8e2caf52a_1864x674.png 424w, https://substackcdn.com/image/fetch/$s_!bl1x!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe566cca1-b67f-4902-9bf9-f0a8e2caf52a_1864x674.png 848w, https://substackcdn.com/image/fetch/$s_!bl1x!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe566cca1-b67f-4902-9bf9-f0a8e2caf52a_1864x674.png 1272w, https://substackcdn.com/image/fetch/$s_!bl1x!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe566cca1-b67f-4902-9bf9-f0a8e2caf52a_1864x674.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><h1>Decoding</h1><p>Now, finally getting into the decoding part. The way a QR code is read is from bottom right to top left following the path shown below. The first 4 bits give us the encoding and the next 8 the length of the message.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Htod!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4541514-8cf6-4408-b63d-57ee758f2926_1960x746.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Htod!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4541514-8cf6-4408-b63d-57ee758f2926_1960x746.png 424w, https://substackcdn.com/image/fetch/$s_!Htod!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4541514-8cf6-4408-b63d-57ee758f2926_1960x746.png 848w, https://substackcdn.com/image/fetch/$s_!Htod!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4541514-8cf6-4408-b63d-57ee758f2926_1960x746.png 1272w, https://substackcdn.com/image/fetch/$s_!Htod!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4541514-8cf6-4408-b63d-57ee758f2926_1960x746.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Htod!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4541514-8cf6-4408-b63d-57ee758f2926_1960x746.png" width="1456" height="554" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b4541514-8cf6-4408-b63d-57ee758f2926_1960x746.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:554,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:303077,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Htod!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4541514-8cf6-4408-b63d-57ee758f2926_1960x746.png 424w, https://substackcdn.com/image/fetch/$s_!Htod!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4541514-8cf6-4408-b63d-57ee758f2926_1960x746.png 848w, https://substackcdn.com/image/fetch/$s_!Htod!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4541514-8cf6-4408-b63d-57ee758f2926_1960x746.png 1272w, https://substackcdn.com/image/fetch/$s_!Htod!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4541514-8cf6-4408-b63d-57ee758f2926_1960x746.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This means, for our QR code, we would have a <strong>0100</strong> encoding, which is a <strong>byte encoding</strong> and a <strong>00001110</strong> message length which is <strong>14</strong>. Byte encoding tells us we&#8217;re expecting blocks of <strong>8 bits</strong> and that <strong>we're expecting 14 of them.</strong> </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ULga!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F114ab16f-4d48-4011-b3a3-2d82786680a3_1998x1082.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ULga!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F114ab16f-4d48-4011-b3a3-2d82786680a3_1998x1082.png 424w, https://substackcdn.com/image/fetch/$s_!ULga!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F114ab16f-4d48-4011-b3a3-2d82786680a3_1998x1082.png 848w, https://substackcdn.com/image/fetch/$s_!ULga!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F114ab16f-4d48-4011-b3a3-2d82786680a3_1998x1082.png 1272w, https://substackcdn.com/image/fetch/$s_!ULga!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F114ab16f-4d48-4011-b3a3-2d82786680a3_1998x1082.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ULga!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F114ab16f-4d48-4011-b3a3-2d82786680a3_1998x1082.png" width="686" height="371.2692307692308" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/114ab16f-4d48-4011-b3a3-2d82786680a3_1998x1082.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:788,&quot;width&quot;:1456,&quot;resizeWidth&quot;:686,&quot;bytes&quot;:163048,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ULga!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F114ab16f-4d48-4011-b3a3-2d82786680a3_1998x1082.png 424w, https://substackcdn.com/image/fetch/$s_!ULga!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F114ab16f-4d48-4011-b3a3-2d82786680a3_1998x1082.png 848w, https://substackcdn.com/image/fetch/$s_!ULga!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F114ab16f-4d48-4011-b3a3-2d82786680a3_1998x1082.png 1272w, https://substackcdn.com/image/fetch/$s_!ULga!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F114ab16f-4d48-4011-b3a3-2d82786680a3_1998x1082.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>We&#8217;re going to continue splitting our QR code into blocks of 8 bits and following the pattern of interleaved blocks below, we should have something similar to the right picture below:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bRcx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F701148d5-ba44-4c3d-86d6-ec3ca4f98bf0_1988x1056.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bRcx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F701148d5-ba44-4c3d-86d6-ec3ca4f98bf0_1988x1056.png 424w, https://substackcdn.com/image/fetch/$s_!bRcx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F701148d5-ba44-4c3d-86d6-ec3ca4f98bf0_1988x1056.png 848w, https://substackcdn.com/image/fetch/$s_!bRcx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F701148d5-ba44-4c3d-86d6-ec3ca4f98bf0_1988x1056.png 1272w, https://substackcdn.com/image/fetch/$s_!bRcx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F701148d5-ba44-4c3d-86d6-ec3ca4f98bf0_1988x1056.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bRcx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F701148d5-ba44-4c3d-86d6-ec3ca4f98bf0_1988x1056.png" width="1456" height="773" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/701148d5-ba44-4c3d-86d6-ec3ca4f98bf0_1988x1056.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:773,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:409870,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!bRcx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F701148d5-ba44-4c3d-86d6-ec3ca4f98bf0_1988x1056.png 424w, https://substackcdn.com/image/fetch/$s_!bRcx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F701148d5-ba44-4c3d-86d6-ec3ca4f98bf0_1988x1056.png 848w, https://substackcdn.com/image/fetch/$s_!bRcx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F701148d5-ba44-4c3d-86d6-ec3ca4f98bf0_1988x1056.png 1272w, https://substackcdn.com/image/fetch/$s_!bRcx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F701148d5-ba44-4c3d-86d6-ec3ca4f98bf0_1988x1056.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>We can see we have indeed 14 blocks. The last block containing the 4 bits of white modules is the <strong>End of message (Terminator) </strong>representing the end of our message. Now that we have our blocks splitted we can start decoding each character. We do this by summing up all the turned on (black) bits and converting the decimal number obtained into its specific character using an ASCII Table. <br><br>This will give us the following:<br><br>64+16+4 = 84 representing T<br>64+32+8 = 104 representing h <br>64+32+4+1 = 101 representing e<br>32 representing " "<br>64+2+1 = 67 representing C<br>64+32+14+4 = 114 representing r<br>64+32+1 = 97 representing a<br>64+32+4+2 = 102 representing f<br>64+32+16+4 = 116 representing t <br>64+32+16+8+1 = 121 representing y<br>32 representing " "<br>64+4 = 68 representing D <br>64+32+4+1 = 101 representing e <br>64+32+16+4+2 = representing v</p><p>We finally decoded our QR code which says &#8220;The Crafty Dev&#8220; &#128588; &#128588; &#128588; .<br><br>The rest of the QR code message is part of the error correction data which we&#8217;ll have a look at in the next article, where we&#8217;ll talk about how QR Codes do error correction while we&#8217;ll also dive into how the Reed-Solomon algorithm works.</p><h1>Conclusion</h1><p>In this article we had a general look at QR Codes, their main components, what unmasking is and how it works, and finally how to decode the QR Code message.</p><p><strong>Stay tuned, </strong>as in the upcoming articles we'll dive deeper into:</p><ol><li><p><strong>On Error Correction: From Hamming to Reed-Solomon</strong></p></li><li><p><strong>QR Code Models</strong></p></li></ol><p>See you soon <a href="https://emojipedia.org/waving-hand">&#128075;</a></p>]]></content:encoded></item><item><title><![CDATA[Least Frequently Used (LFU) Cache - Design and Implementation]]></title><description><![CDATA[On how LFU works and how to implement an optimal solution.]]></description><link>https://blog.diana-enache.com/p/least-frequently-used-lfu-cache-design</link><guid isPermaLink="false">https://blog.diana-enache.com/p/least-frequently-used-lfu-cache-design</guid><dc:creator><![CDATA[Diana Darie]]></dc:creator><pubDate>Thu, 21 Mar 2024 13:40:34 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/b6d5ed26-a480-4ed8-88ec-8244f2c6b4dc_2815x1420.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3>What is LFU Cache?</h3><p>The basic principle of LFU caching is to remove the least frequently used items first when the cache reaches its capacity limit. This means that the cache keeps track of the frequency with which each item is accessed, and when it needs to make space for a new item, it removes the item that has been accessed the least frequently.</p><h3>LFU Cache Design</h3><p>To implement a <a href="https://en.wikipedia.org/wiki/Least_frequently_used">Least Frequently Used (LFU)</a> cache solution we need to design a data structure that would support the following operations:</p><ul><li><p><code>LFUCache(int capacity)</code> - initialises the object with the capacity of the data structure.</p></li><li><p><code>int get(int key)</code> - gets the value of the <code>key</code> if the <code>key</code> exists in the cache. Otherwise, returns <code>-1</code>.</p></li><li><p><code>void put(int key, int value)</code> - updates the value of the <code>key</code> if present, or inserts the <code>key</code> if not already present. When the cache reaches its <code>capacity</code>, it should invalidate and remove the <strong>least frequently used</strong> key before inserting a new item. For this problem, when there is a <strong>tie</strong> (i.e., two or more keys with the same frequency), the <strong>least recently used</strong> <code>key</code> would be invalidated.</p></li></ul><p>The frequency for a <code>key</code> is incremented whenever a <code>get</code> or a <code>put</code> operation is called on the element.</p><p>Let&#8217;s run through an example to better understand how this would work:</p><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/9X8cO/2/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2196645c-cf6c-49cb-9828-60dd9f51cfea_1260x660.png&quot;,&quot;thumbnail_url_full&quot;:&quot;&quot;,&quot;height&quot;:489,&quot;title&quot;:&quot;LFU Cache step-by-step operations&quot;,&quot;description&quot;:&quot;&quot;}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/9X8cO/2/" width="730" height="489" frameborder="0" scrolling="no"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><ol><li><p>Let&#8217;s say we have a cache with a capacity of 2 <code>LFU(2)</code> and we call <code>put(1,1)<br></code>&#8594; Our LFU will become <code>{1,1,1}</code> as we add the<code> key 1</code> with <code>value 1</code> which currently has a <code>frequency of 1</code></p></li><li><p>Then we call <code>put(2,2)</code> &#8594; Our LFU will become <code>{2,2,1},{1,1,1}</code>. We added a new element with <code>key 2 </code>and <code>value 2</code>  which currently has a <code>frequency of 1</code>. Since elements with key 1 and 2 have the same frequency of 1, we add the most recently used element (the one with key 2) to the front of the list. </p></li><li><p>Then we call <code>get(1)</code>. Our LFU will return 1 and the new LFU will be <code>{1,1,2}, {2,2,1}</code>. This is because we increase the frequency of element with key 2 to 2 (due to the read operation) and we move it to the front of the list because it has higher frequency than the other element.</p></li><li><p>Then we call <code>put(3, 3)</code>. Our LFU will become <code>{1,1,2}, {3,3,1}</code>. A new element comes in but our cache is at full capacity so we need to remove an element. We remove from the end of the list (as this is where the element with the least frequency and least recency is stored), so <code>{2,2,1}</code> gets removed. We then add the new element with a frequency of 1, <code>{3,3,1}</code>.</p></li><li><p>We call <code>get(2)</code>. We return <code>-1</code> as the element no longer exists in the cache.</p></li><li><p>We call <code>get(3)</code>. We return <code>3</code> and the LFU becomes <code>{3,3,2}, {1,1,2}</code>. We increase the frequency of 3 and move it before key 1 as even though they have the same frequency, key 3 has been accessed more recently.  </p></li><li><p>We call <code>put(4,4)</code>. The LFU becomes <code>{3,3,2}, {4,4,1}</code>. New element comes in, cache is full, we remove the last element with key 1 and add the new element with key 4.</p></li><li><p>We call <code>get(1)</code>. We return <code>-1</code> as element is no longer present in the cache.</p></li><li><p>We call <code>get(3)</code>. We return <code>3</code> and our LFU becomes <code>{3,3,3}, {4,4,1}</code>. The read operation increases the frequency of element at key 3 to 3.</p></li><li><p>We call <code>get(4)</code>. We return <code>4</code> and our LFU becomes <code>{3,3,3}, {4,4,2}</code>.</p></li></ol><p></p><h3>Possible Implementations</h3><ul><li><p>Using a <strong>brute force approach</strong>, we could have an array with the size of the cache. Each element in the array would store the item along with its frequency and last access time. When we get an element, we&#8217;d have to iterate through the array to find our element and update the item with the incremented frequency value. This means getting an element would be on average <strong>O(n)</strong>. To put an item when the cache is full, we&#8217;d have to look for an item to evict. So we&#8217;ll iterate through the whole array and look for the item with the least frequency and oldest access time. This would take <strong>O(n).</strong></p></li><li><p>Using a <strong>min-heap data structure</strong> would be an improvement - each node will hold the cached element along with its frequency. This makes it easy to remove an element when the cache is full as the least recently and frequently used element will be a the top. The problem comes when inserting or reading from the cache, as any operation will mean the min-heap will need to be rebalanced which will take <strong>O(logn)</strong>. </p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!y6y4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff58d03f3-e3c7-4cac-9983-92f399dad26f_2594x1541.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!y6y4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff58d03f3-e3c7-4cac-9983-92f399dad26f_2594x1541.jpeg 424w, https://substackcdn.com/image/fetch/$s_!y6y4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff58d03f3-e3c7-4cac-9983-92f399dad26f_2594x1541.jpeg 848w, https://substackcdn.com/image/fetch/$s_!y6y4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff58d03f3-e3c7-4cac-9983-92f399dad26f_2594x1541.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!y6y4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff58d03f3-e3c7-4cac-9983-92f399dad26f_2594x1541.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!y6y4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff58d03f3-e3c7-4cac-9983-92f399dad26f_2594x1541.jpeg" width="372" height="221.00274725274724" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f58d03f3-e3c7-4cac-9983-92f399dad26f_2594x1541.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:865,&quot;width&quot;:1456,&quot;resizeWidth&quot;:372,&quot;bytes&quot;:105120,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!y6y4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff58d03f3-e3c7-4cac-9983-92f399dad26f_2594x1541.jpeg 424w, https://substackcdn.com/image/fetch/$s_!y6y4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff58d03f3-e3c7-4cac-9983-92f399dad26f_2594x1541.jpeg 848w, https://substackcdn.com/image/fetch/$s_!y6y4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff58d03f3-e3c7-4cac-9983-92f399dad26f_2594x1541.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!y6y4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff58d03f3-e3c7-4cac-9983-92f399dad26f_2594x1541.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p></p><h3>Solution in constant time</h3><p>To implement an LFU that uses constant time for pushing and getting items, we&#8217;re going to need 2 data structures: a key map and a frequency map.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WWtZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65739174-1f37-4803-adf8-546ea99661c5_3311x1207.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WWtZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65739174-1f37-4803-adf8-546ea99661c5_3311x1207.jpeg 424w, https://substackcdn.com/image/fetch/$s_!WWtZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65739174-1f37-4803-adf8-546ea99661c5_3311x1207.jpeg 848w, https://substackcdn.com/image/fetch/$s_!WWtZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65739174-1f37-4803-adf8-546ea99661c5_3311x1207.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!WWtZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65739174-1f37-4803-adf8-546ea99661c5_3311x1207.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WWtZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65739174-1f37-4803-adf8-546ea99661c5_3311x1207.jpeg" width="602" height="219.54807692307693" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/65739174-1f37-4803-adf8-546ea99661c5_3311x1207.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:531,&quot;width&quot;:1456,&quot;resizeWidth&quot;:602,&quot;bytes&quot;:164010,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!WWtZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65739174-1f37-4803-adf8-546ea99661c5_3311x1207.jpeg 424w, https://substackcdn.com/image/fetch/$s_!WWtZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65739174-1f37-4803-adf8-546ea99661c5_3311x1207.jpeg 848w, https://substackcdn.com/image/fetch/$s_!WWtZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65739174-1f37-4803-adf8-546ea99661c5_3311x1207.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!WWtZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F65739174-1f37-4803-adf8-546ea99661c5_3311x1207.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><ul><li><p><strong>Key Map</strong> - stores the key of the item and the item node containing the key, value and frequency.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GvFO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2963e70-5e45-41be-9451-cb106ef2ee10_1420x820.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GvFO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2963e70-5e45-41be-9451-cb106ef2ee10_1420x820.png 424w, https://substackcdn.com/image/fetch/$s_!GvFO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2963e70-5e45-41be-9451-cb106ef2ee10_1420x820.png 848w, https://substackcdn.com/image/fetch/$s_!GvFO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2963e70-5e45-41be-9451-cb106ef2ee10_1420x820.png 1272w, https://substackcdn.com/image/fetch/$s_!GvFO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2963e70-5e45-41be-9451-cb106ef2ee10_1420x820.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GvFO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2963e70-5e45-41be-9451-cb106ef2ee10_1420x820.png" width="620" height="358.0281690140845" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b2963e70-5e45-41be-9451-cb106ef2ee10_1420x820.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:820,&quot;width&quot;:1420,&quot;resizeWidth&quot;:620,&quot;bytes&quot;:104722,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!GvFO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2963e70-5e45-41be-9451-cb106ef2ee10_1420x820.png 424w, https://substackcdn.com/image/fetch/$s_!GvFO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2963e70-5e45-41be-9451-cb106ef2ee10_1420x820.png 848w, https://substackcdn.com/image/fetch/$s_!GvFO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2963e70-5e45-41be-9451-cb106ef2ee10_1420x820.png 1272w, https://substackcdn.com/image/fetch/$s_!GvFO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2963e70-5e45-41be-9451-cb106ef2ee10_1420x820.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Code available on <a href="https://gist.github.com/yumed15/fd3b7d62793eb150f827ce1a2639857c">gist</a></figcaption></figure></div><ul><li><p><strong>Frequency Map</strong> - stores the frequency as key and a doubly linked list of all the cached items having that frequency as value. The items in the doubly linked list are sorted by recency such that most recently accessed items will be at the head of the list and the least recently used at the tail. Due to the nature of the doubly linked list, removing, adding and updating a cached item will take O(1).</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xMyI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F41e76fcc-f0ba-4302-94a6-b98ebdf25ee1_1432x694.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xMyI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F41e76fcc-f0ba-4302-94a6-b98ebdf25ee1_1432x694.png 424w, https://substackcdn.com/image/fetch/$s_!xMyI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F41e76fcc-f0ba-4302-94a6-b98ebdf25ee1_1432x694.png 848w, https://substackcdn.com/image/fetch/$s_!xMyI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F41e76fcc-f0ba-4302-94a6-b98ebdf25ee1_1432x694.png 1272w, https://substackcdn.com/image/fetch/$s_!xMyI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F41e76fcc-f0ba-4302-94a6-b98ebdf25ee1_1432x694.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xMyI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F41e76fcc-f0ba-4302-94a6-b98ebdf25ee1_1432x694.png" width="626" height="303.3826815642458" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/41e76fcc-f0ba-4302-94a6-b98ebdf25ee1_1432x694.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:694,&quot;width&quot;:1432,&quot;resizeWidth&quot;:626,&quot;bytes&quot;:114052,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!xMyI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F41e76fcc-f0ba-4302-94a6-b98ebdf25ee1_1432x694.png 424w, https://substackcdn.com/image/fetch/$s_!xMyI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F41e76fcc-f0ba-4302-94a6-b98ebdf25ee1_1432x694.png 848w, https://substackcdn.com/image/fetch/$s_!xMyI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F41e76fcc-f0ba-4302-94a6-b98ebdf25ee1_1432x694.png 1272w, https://substackcdn.com/image/fetch/$s_!xMyI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F41e76fcc-f0ba-4302-94a6-b98ebdf25ee1_1432x694.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Code available on <a href="https://gist.github.com/yumed15/edb527ea14cf62867341966704a9e227">gist</a></figcaption></figure></div><p>Given those two data structures, the cache operations would have the following logic:</p><ul><li><p><code>get</code> operation for an item X:</p><ul><li><p>check that X is in our key map. If it doesn&#8217;t exist return -1. Otherwise get the frequency from the value node.</p></li><li><p>for the frequency we&#8217;ve obtained above, get the doubly linked list from the frequency map. Delete the node from the doubly linked list. Create a new node with the incremented frequency and added it to the frequency map at the head of the doubly linked list.</p><p><br>Following the above instructions, the implementation for the <code>get</code> operation should look similar to this:</p></li></ul></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!myLs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F040e5341-9e77-4ac5-9746-819582e864b8_1414x1426.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!myLs!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F040e5341-9e77-4ac5-9746-819582e864b8_1414x1426.png 424w, https://substackcdn.com/image/fetch/$s_!myLs!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F040e5341-9e77-4ac5-9746-819582e864b8_1414x1426.png 848w, https://substackcdn.com/image/fetch/$s_!myLs!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F040e5341-9e77-4ac5-9746-819582e864b8_1414x1426.png 1272w, https://substackcdn.com/image/fetch/$s_!myLs!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F040e5341-9e77-4ac5-9746-819582e864b8_1414x1426.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!myLs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F040e5341-9e77-4ac5-9746-819582e864b8_1414x1426.png" width="698" height="703.9236209335219" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/040e5341-9e77-4ac5-9746-819582e864b8_1414x1426.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1426,&quot;width&quot;:1414,&quot;resizeWidth&quot;:698,&quot;bytes&quot;:258227,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!myLs!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F040e5341-9e77-4ac5-9746-819582e864b8_1414x1426.png 424w, https://substackcdn.com/image/fetch/$s_!myLs!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F040e5341-9e77-4ac5-9746-819582e864b8_1414x1426.png 848w, https://substackcdn.com/image/fetch/$s_!myLs!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F040e5341-9e77-4ac5-9746-819582e864b8_1414x1426.png 1272w, https://substackcdn.com/image/fetch/$s_!myLs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F040e5341-9e77-4ac5-9746-819582e864b8_1414x1426.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Code available on <a href="https://gist.github.com/d0282a95407825fab8739e1c9b46ec3c.git">gist</a></figcaption></figure></div><ul><li><p><code>put</code> operation for an item X:</p><ul><li><p>if the item already exists in the cache, it returns the node and updates the frequency (hence, we call <code>getNode </code>which does all of these)</p></li><li><p>if the item doesn&#8217;t exist in the cache:</p><ul><li><p>if the cache is full - we remove the least recently and frequency used item, which should be the tail of the doubly linked list value in the frequency map with the minimum frequency.</p></li><li><p>then we add the item at the head of the doubly linked list with has the frequency of <code>1</code></p></li></ul><p><br>Considering the above, the implementation for the put operation would look like: </p></li></ul></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fnz1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18d8d068-2ae8-4c66-b274-1c42c4c01047_1416x1520.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fnz1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18d8d068-2ae8-4c66-b274-1c42c4c01047_1416x1520.png 424w, https://substackcdn.com/image/fetch/$s_!fnz1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18d8d068-2ae8-4c66-b274-1c42c4c01047_1416x1520.png 848w, https://substackcdn.com/image/fetch/$s_!fnz1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18d8d068-2ae8-4c66-b274-1c42c4c01047_1416x1520.png 1272w, https://substackcdn.com/image/fetch/$s_!fnz1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18d8d068-2ae8-4c66-b274-1c42c4c01047_1416x1520.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fnz1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18d8d068-2ae8-4c66-b274-1c42c4c01047_1416x1520.png" width="666" height="714.9152542372881" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/18d8d068-2ae8-4c66-b274-1c42c4c01047_1416x1520.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1520,&quot;width&quot;:1416,&quot;resizeWidth&quot;:666,&quot;bytes&quot;:313511,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!fnz1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18d8d068-2ae8-4c66-b274-1c42c4c01047_1416x1520.png 424w, https://substackcdn.com/image/fetch/$s_!fnz1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18d8d068-2ae8-4c66-b274-1c42c4c01047_1416x1520.png 848w, https://substackcdn.com/image/fetch/$s_!fnz1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18d8d068-2ae8-4c66-b274-1c42c4c01047_1416x1520.png 1272w, https://substackcdn.com/image/fetch/$s_!fnz1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18d8d068-2ae8-4c66-b274-1c42c4c01047_1416x1520.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Code available on <a href="https://gist.github.com/810c91ff8a5caa9dcc498be6f727608a.git">gist</a></figcaption></figure></div><p>Putting everything together, the code should look like <a href="https://gist.github.com/b0367f776eed85e5a4c24dce48070314.git">this</a>. </p><h3>Conclusion</h3><p>In this article we had a look on how we would go about implementing an LFU. </p><p>To learn more about caching, have a look at the following articles:</p><ul><li><p><a href="https://thecraftydev.substack.com/p/mastering-cache-management-eviction">Mastering Cache Management: Eviction, Invalidation, and Optimal Data Access Strategies</a></p></li></ul><p>Or <strong>stay tuned </strong>as in the upcoming articles, we'll dive deeper into:</p><ul><li><p><strong>Types of Caches:</strong> Exploring different caching mechanisms like in-memory, distributed, and CDN caching.</p></li><li><p><strong>Deployment Strategies:</strong> Understanding how to integrate caching into your architecture.</p></li><li><p><strong>Metrics:</strong> How to monitor cache performance for optimal results.</p></li><li><p><strong>Implementation Solutions:</strong> Practical examples with popular caching tools and libraries.</p></li></ul>]]></content:encoded></item><item><title><![CDATA[Mastering Cache Management: Eviction, Invalidation, and Optimal Data Access Strategies]]></title><description><![CDATA[On caching, what it is, when to use it, benefits, eviction policies, invalidation strategies and read/write flows]]></description><link>https://blog.diana-enache.com/p/mastering-cache-management-eviction</link><guid isPermaLink="false">https://blog.diana-enache.com/p/mastering-cache-management-eviction</guid><dc:creator><![CDATA[Diana Darie]]></dc:creator><pubDate>Wed, 06 Mar 2024 11:43:51 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe06d517a-59c2-4bbe-a7e7-c83fc5d46dfa_1912x2091.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A cache is a temporary storage area that improves performance by storing data closer to where it's needed, minimising trips to main storage or external systems. Think of a cache like your browser saving recently visited websites: instead of reloading everything from the internet, it provides a faster experience by using the local copy.</p><p><strong>When to use it</strong> :</p><ul><li><p>for <strong>frequently accessed data</strong> - e.g. website assets, session data, popular content</p></li><li><p>for <strong>expensive operations</strong> - database queries (if the same complex query is frequently executed), API calls (e.g. weather data, currency conversions), compute intensive calculations</p></li><li><p>for times <strong>when speed is paramount</strong> - high-traffic websites (reduce strain on the backend by serving frequent requests), search suggestion (autocomplete features often use a cache to display results instantly as the user types)</p></li></ul><p>When accessing data from a cache, there's a best-case and a fallback scenario. A <strong>cache hit</strong> means the data was found in the cache, leading to a speedy response. A <strong>cache miss</strong> means the data wasn't present, so the system will need to fetch it from the slower main storage.</p><p><strong>What to consider:</strong> </p><ul><li><p><strong>Amdahl&#8217;s Law</strong> - <em>&#8220;the overall performance improvement gained by optimizing a single part of a system is limited by the fraction of time that the improved part is actually used&#8221;</em></p><ul><li><p><strong>Diminishing Returns:</strong> Cache hit rates matter immensely. The initial gains from adding a cache are often dramatic. But, according to Amdahl's Law, as you reach 90, 95, 98% hit rates, the effort to squeeze more performance decreases in effectiveness.</p></li></ul></li><li><p><strong>Pareto Distribution</strong> - &#8220;also known as the &#8220;80-20 rule&#8221; stating that 80% of outcomes are due to 20% of causes&#8220;</p><ul><li><p><strong>Cache Misses Are </strong><em><strong>Not</strong></em><strong> Evenly Distributed:</strong> In many systems, some data is far more popular than others. Picture the top 10% of products on an e-commerce site getting 60% of the traffic. This skewed access pattern aligns with the Pareto principle. To get the caching wins, you need to first analyse your data to see if the access patterns truly exhibit Pareto-like characteristics.</p></li></ul></li></ul><h3>Cache Benefits</h3><ul><li><p><strong>Faster Access and</strong> <strong>Reduced Latency</strong> - serving data from in-memory stores vs. databases or external APIs offers massive latency gains.</p></li><li><p><strong>Bandwidth Optimisation</strong> - when external API calls or media assets are cached, you can potentially decrease bandwidth usage.</p></li><li><p><strong>Reduced Database Costs </strong>- databases are often a significant cost factor. Offloading queries to a cache can directly lower your database-related expenses.</p></li><li><p><strong>Improved Throughput</strong> - when a cache satisfies a request, your main database or origin servers are untouched. This allows your system to handle more concurrent users without overwhelming core resources.</p></li><li><p><strong>Handle Spikes</strong> - sudden surges that would cripple an uncached system can often be served smoothly when a cache absorbs the brunt of those requests.</p></li></ul><h3>Cache Eviction Policies</h3><p>A caching eviction policy determines how a cache handles the data eviction when the cache is full. When an item is requested from the cache, it may result in a miss, which means data needs to be fetched from the database and the cache needs to be updated. But before doing that, an item needs to be removed. The following section describes several strategies on how to choose which item to pick.  </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cbDV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64517f5b-88c6-468d-8fc6-a5ab229ea3af_2936x1361.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cbDV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64517f5b-88c6-468d-8fc6-a5ab229ea3af_2936x1361.jpeg 424w, https://substackcdn.com/image/fetch/$s_!cbDV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64517f5b-88c6-468d-8fc6-a5ab229ea3af_2936x1361.jpeg 848w, https://substackcdn.com/image/fetch/$s_!cbDV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64517f5b-88c6-468d-8fc6-a5ab229ea3af_2936x1361.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!cbDV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64517f5b-88c6-468d-8fc6-a5ab229ea3af_2936x1361.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cbDV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64517f5b-88c6-468d-8fc6-a5ab229ea3af_2936x1361.jpeg" width="638" height="295.7760989010989" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/64517f5b-88c6-468d-8fc6-a5ab229ea3af_2936x1361.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:675,&quot;width&quot;:1456,&quot;resizeWidth&quot;:638,&quot;bytes&quot;:137996,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!cbDV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64517f5b-88c6-468d-8fc6-a5ab229ea3af_2936x1361.jpeg 424w, https://substackcdn.com/image/fetch/$s_!cbDV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64517f5b-88c6-468d-8fc6-a5ab229ea3af_2936x1361.jpeg 848w, https://substackcdn.com/image/fetch/$s_!cbDV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64517f5b-88c6-468d-8fc6-a5ab229ea3af_2936x1361.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!cbDV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64517f5b-88c6-468d-8fc6-a5ab229ea3af_2936x1361.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Flow when a request results in a cache miss</figcaption></figure></div><ul><li><p><strong>Queue-Based Policies</strong> </p><ul><li><p><strong>FIFO</strong> (First-In-First-Out)</p><ul><li><p><strong>Process:</strong> The first in/oldest item gets removed to make space for the new item, which is then added to the end.</p></li><li><p><strong>Pros:</strong></p><ul><li><p><strong>Simplicity:</strong> Very easy to implement and understand.</p></li><li><p><strong>Fairness (Of Sorts):</strong> Prevents any item from 'hogging' the cache indefinitely if there's a steady stream of new data.</p></li></ul></li><li><p><strong>Cons:</strong></p><ul><li><p><strong>Inefficient for Many Workloads:</strong> Real-world data access patterns often aren't purely FIFO order. An item used constantly might get evicted simply because it was added a while ago, leading to repetitive refetches of the same thing.</p></li><li><p><strong>Ignores Popularity:</strong> A popular item accessed right after eviction will need to be fetched again, even though there may be other rarely-used data in the cache.</p></li></ul></li></ul></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1nL9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40be41c4-cd31-4e8b-8a8b-dd402f7ecbb7_3160x1265.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1nL9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40be41c4-cd31-4e8b-8a8b-dd402f7ecbb7_3160x1265.jpeg 424w, https://substackcdn.com/image/fetch/$s_!1nL9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40be41c4-cd31-4e8b-8a8b-dd402f7ecbb7_3160x1265.jpeg 848w, https://substackcdn.com/image/fetch/$s_!1nL9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40be41c4-cd31-4e8b-8a8b-dd402f7ecbb7_3160x1265.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!1nL9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40be41c4-cd31-4e8b-8a8b-dd402f7ecbb7_3160x1265.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1nL9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40be41c4-cd31-4e8b-8a8b-dd402f7ecbb7_3160x1265.jpeg" width="1456" height="583" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/40be41c4-cd31-4e8b-8a8b-dd402f7ecbb7_3160x1265.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:583,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:81096,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1nL9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40be41c4-cd31-4e8b-8a8b-dd402f7ecbb7_3160x1265.jpeg 424w, https://substackcdn.com/image/fetch/$s_!1nL9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40be41c4-cd31-4e8b-8a8b-dd402f7ecbb7_3160x1265.jpeg 848w, https://substackcdn.com/image/fetch/$s_!1nL9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40be41c4-cd31-4e8b-8a8b-dd402f7ecbb7_3160x1265.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!1nL9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40be41c4-cd31-4e8b-8a8b-dd402f7ecbb7_3160x1265.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Data eviction following a FIFO approach</figcaption></figure></div><ul><li><p><strong>LIFO</strong> (Last-In-First-Out)</p><ul><li><p><strong>Process:</strong> The last in/newest item gets removed to make space for the new item, which is then added to the end.</p></li><li><p><strong>Pros:</strong> Same as FIFO</p></li><li><p><strong>Cons:</strong> Same as FIFO</p></li></ul></li></ul></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qVUg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64395809-0129-4f25-9215-a28098fbff77_2709x1476.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qVUg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64395809-0129-4f25-9215-a28098fbff77_2709x1476.jpeg 424w, https://substackcdn.com/image/fetch/$s_!qVUg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64395809-0129-4f25-9215-a28098fbff77_2709x1476.jpeg 848w, https://substackcdn.com/image/fetch/$s_!qVUg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64395809-0129-4f25-9215-a28098fbff77_2709x1476.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!qVUg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64395809-0129-4f25-9215-a28098fbff77_2709x1476.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qVUg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64395809-0129-4f25-9215-a28098fbff77_2709x1476.jpeg" width="586" height="319.1607142857143" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/64395809-0129-4f25-9215-a28098fbff77_2709x1476.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:793,&quot;width&quot;:1456,&quot;resizeWidth&quot;:586,&quot;bytes&quot;:83740,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!qVUg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64395809-0129-4f25-9215-a28098fbff77_2709x1476.jpeg 424w, https://substackcdn.com/image/fetch/$s_!qVUg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64395809-0129-4f25-9215-a28098fbff77_2709x1476.jpeg 848w, https://substackcdn.com/image/fetch/$s_!qVUg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64395809-0129-4f25-9215-a28098fbff77_2709x1476.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!qVUg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64395809-0129-4f25-9215-a28098fbff77_2709x1476.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Data eviction following a LIFO approach</figcaption></figure></div><ul><li><p><strong>Recency-Based Policies</strong></p><ul><li><p><strong>LRU</strong> (Least Recently Used)</p><ul><li><p><strong>Process:</strong> The basic principle of LRU caching is to remove the least recently used items first when the cache reaches its capacity limit. This means that the cache keeps track of the order in which items are accessed, and when it needs to make space for a new item, it removes the least recently accessed item.</p></li><li><p><strong>Pros:</strong></p><ul><li><p><strong>Effective use of cache space:</strong> LRU caching maximizes the utilization of cache space by keeping frequently accessed items in memory.</p></li><li><p><strong>Good performance:</strong> LRU caching performs well in scenarios where there is a high degree of temporal locality, such as web servers and databases.</p></li><li><p><strong>Simple implementation:</strong> The basic LRU caching algorithm is relatively simple to implement and understand.</p></li></ul></li><li><p><strong>Cons:</strong></p><ul><li><p><strong>Overhead:</strong> LRU caching requires additional data structures to keep track of access history, which can introduce overhead in terms of memory and computational resources.</p></li><li><p><strong>Not suitable for all access patterns:</strong> LRU caching may not perform optimally in scenarios with non-temporal access patterns or where access frequencies vary widely.</p></li></ul></li><li><p><strong>Possible implementation:</strong></p><ul><li><p>An LRU cache is often implemented by pairing a doubly linked list with a hash map. The linked list is set up with the most-recently used item at the head of the list and the least-recently used item at the tail.</p></li><li><p>When we get a request, we first look up the item in our hash map:</p><ul><li><p>if it&#8217;s there,  it&#8217;s a cache hit:</p><ul><li><p>we use the hash map to quickly find the corresponding linked list node.</p></li><li><p>we then move the item's linked list node to the head of the linked list, since it's now the most recently used (so it shouldn't get evicted any time soon).</p></li></ul></li><li><p>if it&#8217;s not there, it&#8217;s a cache miss: </p><ul><li><p>if the cache is full - we evit the least recently used item which should be at the end of the queue.</p></li><li><p>we create a new linked list node and add it at the head of the queue and update the hashmap where the value points to the node we&#8217;ve just inserted. </p></li></ul></li></ul></li></ul></li></ul></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CmXF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f6bcb53-cb6c-4bfb-ba97-99db1c178f2d_2923x1368.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CmXF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f6bcb53-cb6c-4bfb-ba97-99db1c178f2d_2923x1368.jpeg 424w, https://substackcdn.com/image/fetch/$s_!CmXF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f6bcb53-cb6c-4bfb-ba97-99db1c178f2d_2923x1368.jpeg 848w, https://substackcdn.com/image/fetch/$s_!CmXF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f6bcb53-cb6c-4bfb-ba97-99db1c178f2d_2923x1368.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!CmXF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f6bcb53-cb6c-4bfb-ba97-99db1c178f2d_2923x1368.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CmXF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f6bcb53-cb6c-4bfb-ba97-99db1c178f2d_2923x1368.jpeg" width="1456" height="681" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2f6bcb53-cb6c-4bfb-ba97-99db1c178f2d_2923x1368.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:681,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:141235,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!CmXF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f6bcb53-cb6c-4bfb-ba97-99db1c178f2d_2923x1368.jpeg 424w, https://substackcdn.com/image/fetch/$s_!CmXF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f6bcb53-cb6c-4bfb-ba97-99db1c178f2d_2923x1368.jpeg 848w, https://substackcdn.com/image/fetch/$s_!CmXF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f6bcb53-cb6c-4bfb-ba97-99db1c178f2d_2923x1368.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!CmXF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2f6bcb53-cb6c-4bfb-ba97-99db1c178f2d_2923x1368.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Data eviction following a LRU approach</figcaption></figure></div><ul><li><p><strong>MRU</strong> (Most Recently Used)</p><ul><li><p><strong>Process:</strong> evicts the most recently accessed data item from the cache. When a new item needs to be added to the cache and it's already at full capacity, the cache algorithm looks at the usage history of the items and evicts the most recently used one. This makes room for the new item to be added. MRU can be useful in scenarios where a small subset of items is accessed frequently.</p></li><li><p><strong>Pros</strong>: Same as LRU</p></li><li><p><strong>Cons</strong>: Same as LRU</p></li></ul></li></ul></li><li><p><strong>Frequency-Based Policies</strong></p><ul><li><p><strong>LFU</strong> (Least Frequently Used)</p><ul><li><p><strong>Process:</strong> The basic principle of LFU caching is to remove the least frequently used items first when the cache reaches its capacity limit. This means that the cache keeps track of the frequency with which each item is accessed, and when it needs to make space for a new item, it removes the item that has been accessed the least frequently.</p></li><li><p><strong>Pros:</strong></p><ul><li><p><strong>Effective use of cache space</strong>: LFU caching maximizes the utilization of cache space by keeping frequently accessed items in memory.</p></li><li><p><strong>Good performance:</strong> LFU caching performs well in scenarios where there are consistent access patterns and certain items are accessed more frequently than others.</p></li><li><p><strong>Adaptive:</strong> LFU caching dynamically adjusts to changes in access patterns, ensuring that frequently accessed items remain in the cache.</p></li></ul></li><li><p><strong>Cons:</strong></p><ul><li><p><strong>Complexity:</strong> LFU caching algorithms can be more complex to implement and maintain compared to simpler caching strategies like LRU (Least Recently Used).</p></li><li><p><strong>Overhead:</strong> LFU caching requires additional data structures to track the access frequency of items, which can introduce overhead in terms of memory and computational resources.</p></li><li><p><strong>Sensitivity to outliers:</strong> LFU caching may not perform optimally in scenarios with highly variable access patterns or sudden spikes in access frequency. Outliers in access frequency can skew the effectiveness of the cache.</p></li></ul></li><li><p><strong>Possible Implementation:</strong></p><ul><li><p>We are going to need 2 data structures, a <strong>cache map</strong> HashMap&lt;item, Node&gt; which holds our item along with a Node object <br><br><code>Node(int val, int key) {</code></p><p><code>&#8195;this.val = val;</code></p><p><code>&#8195;this.key = key;</code></p><p><code>&#8195;this.frequency = 1;</code></p><p><code>}</code><br><br>and a <strong>frequency map</strong> HashMap&lt;count, DoublyLinkedList&lt;Node object&gt;&gt; which holds the count or frequency value a long with a list of all the items that have that given frequency.</p></li><li><p>When the cache is full, the next element that needs to be removed is the tail element of the doubly linked list with the least frequency.</p></li></ul></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!MLoc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F474370e1-9188-4bfe-be5b-bbe87865b775_2693x1485.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MLoc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F474370e1-9188-4bfe-be5b-bbe87865b775_2693x1485.jpeg 424w, https://substackcdn.com/image/fetch/$s_!MLoc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F474370e1-9188-4bfe-be5b-bbe87865b775_2693x1485.jpeg 848w, https://substackcdn.com/image/fetch/$s_!MLoc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F474370e1-9188-4bfe-be5b-bbe87865b775_2693x1485.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!MLoc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F474370e1-9188-4bfe-be5b-bbe87865b775_2693x1485.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!MLoc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F474370e1-9188-4bfe-be5b-bbe87865b775_2693x1485.jpeg" width="1456" height="803" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/474370e1-9188-4bfe-be5b-bbe87865b775_2693x1485.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:803,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:166860,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!MLoc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F474370e1-9188-4bfe-be5b-bbe87865b775_2693x1485.jpeg 424w, https://substackcdn.com/image/fetch/$s_!MLoc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F474370e1-9188-4bfe-be5b-bbe87865b775_2693x1485.jpeg 848w, https://substackcdn.com/image/fetch/$s_!MLoc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F474370e1-9188-4bfe-be5b-bbe87865b775_2693x1485.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!MLoc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F474370e1-9188-4bfe-be5b-bbe87865b775_2693x1485.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Data eviction following a LFU approach</figcaption></figure></div></li><li><p><strong>LFRU</strong> (Least Frequently Recently Used)</p><ul><li><p><strong>Process:</strong> based on a hybrid algorithm that combines aspects of both LFU (Least Frequently Used) and LRU (Least Recently Used) caching strategies. LFRU caching maintains both frequency and recency information for each item in the cache. It tracks how frequently an item is accessed (similar to LFU) and how recently it was accessed (similar to LRU). When a new item needs to be added to the cache and it's already at full capacity, the cache algorithm uses a combination of frequency and recency information to decide which item to evict.</p><ul><li><p>If an item has a low frequency of access but was accessed recently, it may be considered valuable and kept in the cache.</p></li><li><p>If an item has a high frequency of access but hasn't been accessed recently, it may be considered less valuable and evicted from the cache.</p></li></ul></li><li><p><strong>Pros:</strong></p><ul><li><p><strong>Balance</strong>: LFRU caching strikes a balance between considering both frequency and recency of access, leading to more nuanced cache management decisions.</p></li><li><p><strong>Adaptability</strong>: LFRU caching adapts well to varying access patterns and workload changes, ensuring efficient use of cache space.</p></li><li><p><strong>Performance</strong>: LFRU caching can provide good performance by retaining frequently accessed items while also accommodating recent access patterns.</p></li></ul></li><li><p><strong>Cons:</strong></p><ul><li><p><strong>Complexity</strong>: LFRU caching algorithms can be complex to implement and may require additional computational overhead compared to simpler caching strategies.</p></li><li><p><strong>Resource Consumption</strong>: Maintaining both frequency and recency information for each item in the cache may consume more memory and computational resources.</p></li><li><p><strong>Tuning</strong>: Tuning the parameters of an LFRU caching algorithm to optimize performance may require careful experimentation and analysis.</p></li></ul></li></ul></li></ul></li></ul><h3>Cache Invalidation</h3><p>Cache invalidation is the process of removing or marking as invalid data in a cache system. Implementing effective cache invalidation strategies is vital for preserving data integrity and preventing the delivery of stale or obsolete data.</p><ul><li><p><strong>Invalidating on Write</strong></p><ul><li><p>This cache invalidation happens upon modifications to the underlying data source. Whenever a modification operation, like an update or deletion, takes place, the cache is notified or marked to invalidate the associated cached data. Subsequent attempts to access the invalidated data result in cache misses, prompting the retrieval of the latest information from the data source. While this method reduces the risk of serving outdated data, it may introduce a slight delay due to cache misses during the invalidation process.</p></li></ul></li><li><p><strong>Invalidating on Read</strong></p><ul><li><p>Cache invalidation occurs during data access or retrieval. When a read request is received, the cache verifies whether the cached data is still valid or has become outdated. If the data has expired or is marked as invalid, the cache retrieves the latest information from the data source and updates its contents before fulfilling the request. While this method ensures the delivery of up-to-date data, it introduces overhead to each read operation as the cache must confirm the freshness of the data before responding.</p></li></ul></li><li><p><strong>Write-Through Invalidation</strong></p><ul><li><p>In systems where data is written directly to the cache and the source of truth simultaneously, cache entries are invalidated whenever data is written or updated in the source of truth.</p></li></ul></li><li><p><strong>Time Based Invalidation</strong></p><ul><li><p>Cached data is invalidated after a certain period of time has elapsed. For example, a web page cache may be configured to invalidate its content every hour to ensure that users see the most recent version of the page.</p></li></ul></li><li><p><strong>Time-to-Live (TTL)</strong></p><ul><li><p>Similar to time based invalidation, TTL associates a time duration with each cached item. When an item is stored in the cache, it is marked with a TTL value indicating how long the item is considered valid.</p></li></ul></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!BRP1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34d84e33-911c-4670-9043-c2e20bb85b22_2227x1795.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!BRP1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34d84e33-911c-4670-9043-c2e20bb85b22_2227x1795.jpeg 424w, https://substackcdn.com/image/fetch/$s_!BRP1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34d84e33-911c-4670-9043-c2e20bb85b22_2227x1795.jpeg 848w, https://substackcdn.com/image/fetch/$s_!BRP1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34d84e33-911c-4670-9043-c2e20bb85b22_2227x1795.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!BRP1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34d84e33-911c-4670-9043-c2e20bb85b22_2227x1795.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!BRP1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34d84e33-911c-4670-9043-c2e20bb85b22_2227x1795.jpeg" width="1456" height="1174" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/34d84e33-911c-4670-9043-c2e20bb85b22_2227x1795.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1174,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:191514,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!BRP1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34d84e33-911c-4670-9043-c2e20bb85b22_2227x1795.jpeg 424w, https://substackcdn.com/image/fetch/$s_!BRP1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34d84e33-911c-4670-9043-c2e20bb85b22_2227x1795.jpeg 848w, https://substackcdn.com/image/fetch/$s_!BRP1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34d84e33-911c-4670-9043-c2e20bb85b22_2227x1795.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!BRP1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F34d84e33-911c-4670-9043-c2e20bb85b22_2227x1795.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Cache Invalidation Strategies</figcaption></figure></div><h3>Caching Strategies</h3><ul><li><p><strong>Read Strategies</strong></p><ul><li><p><strong>Cache Aside </strong>- also known as lazy loading or lazy population, is a caching strategy where the application is responsible for managing the cache directly. When data is requested, the application first checks the cache. If the data is found, it is returned from the cache. If the data is not in the cache, the application retrieves it from the data source, stores it in the cache, and then returns it to the caller.</p><ul><li><p><strong>Pros</strong>:</p><ul><li><p><strong>Flexibility:</strong> Cache-aside allows applications to cache data selectively, based on their specific requirements. This flexibility enables developers to optimize caching for performance and efficiency.</p></li><li><p><strong>Control:</strong> Applications have full control over cache management, including when to populate, update, or evict cached data. This level of control allows for fine-tuning cache behavior to suit the application's needs.</p></li><li><p><strong>Reduced Load:</strong> By caching frequently accessed data, cache-aside can reduce the load on the primary data source, leading to improved overall system performance and scalability.</p></li></ul></li><li><p><strong>Cons</strong>: </p><ul><li><p><strong>Stale Data:</strong> Without proactive cache population or expiration mechanisms, cache-aside may lead to serving stale or outdated data to users, particularly if data changes frequently in the primary data source.</p></li><li><p><strong>Consistency Challenges:</strong> Ensuring consistency between the cache and the primary data source can be complex, particularly in scenarios involving distributed caching or multiple cache instances. Inconsistent data can lead to data integrity issues and user experience problems.</p></li></ul></li></ul></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!tPbK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa06879d4-2551-406e-9f72-f6b8df9c4a45_3486x1147.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tPbK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa06879d4-2551-406e-9f72-f6b8df9c4a45_3486x1147.jpeg 424w, https://substackcdn.com/image/fetch/$s_!tPbK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa06879d4-2551-406e-9f72-f6b8df9c4a45_3486x1147.jpeg 848w, https://substackcdn.com/image/fetch/$s_!tPbK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa06879d4-2551-406e-9f72-f6b8df9c4a45_3486x1147.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!tPbK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa06879d4-2551-406e-9f72-f6b8df9c4a45_3486x1147.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!tPbK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa06879d4-2551-406e-9f72-f6b8df9c4a45_3486x1147.jpeg" width="1456" height="479" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a06879d4-2551-406e-9f72-f6b8df9c4a45_3486x1147.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:479,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:171275,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!tPbK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa06879d4-2551-406e-9f72-f6b8df9c4a45_3486x1147.jpeg 424w, https://substackcdn.com/image/fetch/$s_!tPbK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa06879d4-2551-406e-9f72-f6b8df9c4a45_3486x1147.jpeg 848w, https://substackcdn.com/image/fetch/$s_!tPbK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa06879d4-2551-406e-9f72-f6b8df9c4a45_3486x1147.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!tPbK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa06879d4-2551-406e-9f72-f6b8df9c4a45_3486x1147.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Cache Aside Flow</figcaption></figure></div><ul><li><p><strong>Read Through </strong>- caching strategy where the application reads data from the cache, and if the requested data is not found in the cache (cache miss), the cache automatically fetches the data from the primary data source (such as a database) and populates the cache with the retrieved data before returning it to the application.</p><ul><li><p><strong>Pros</strong>:</p><ul><li><p><strong>Automatic Population:</strong> Cache read-through automatically populates the cache with requested data, reducing the need for explicit cache management.</p></li><li><p><strong>Simplicity:</strong> Implementing cache read-through is relatively straightforward, as the caching logic is encapsulated within the cache itself, simplifying application code.</p></li></ul></li><li><p><strong>Cons:</strong></p><ul><li><p><strong>Complexity in Eviction:</strong> Managing cache eviction policies to make room for new data can be challenging, especially in scenarios with limited cache capacity or high data volatility.</p></li><li><p><strong>Resource Consumption:</strong> Cache read-through can consume additional system resources, such as memory and network bandwidth, particularly during cache population operations.</p></li></ul></li></ul></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!OCx1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff54ea5b0-b2cf-4282-bc07-3d10e4737b51_3421x1169.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!OCx1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff54ea5b0-b2cf-4282-bc07-3d10e4737b51_3421x1169.jpeg 424w, https://substackcdn.com/image/fetch/$s_!OCx1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff54ea5b0-b2cf-4282-bc07-3d10e4737b51_3421x1169.jpeg 848w, https://substackcdn.com/image/fetch/$s_!OCx1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff54ea5b0-b2cf-4282-bc07-3d10e4737b51_3421x1169.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!OCx1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff54ea5b0-b2cf-4282-bc07-3d10e4737b51_3421x1169.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!OCx1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff54ea5b0-b2cf-4282-bc07-3d10e4737b51_3421x1169.jpeg" width="1456" height="498" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f54ea5b0-b2cf-4282-bc07-3d10e4737b51_3421x1169.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:498,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:178991,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!OCx1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff54ea5b0-b2cf-4282-bc07-3d10e4737b51_3421x1169.jpeg 424w, https://substackcdn.com/image/fetch/$s_!OCx1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff54ea5b0-b2cf-4282-bc07-3d10e4737b51_3421x1169.jpeg 848w, https://substackcdn.com/image/fetch/$s_!OCx1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff54ea5b0-b2cf-4282-bc07-3d10e4737b51_3421x1169.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!OCx1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff54ea5b0-b2cf-4282-bc07-3d10e4737b51_3421x1169.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Cache Read Through Flow</figcaption></figure></div><ul><li><p><strong>Refresh Ahead </strong>- also known as cache pre-loading or cache warm-up, is a caching strategy where the cache proactively fetches and stores data from the primary data source before it is requested by the application. This anticipatory approach aims to populate the cache with frequently accessed or critical data in advance, thereby reducing latency and improving overall system performance.</p><ul><li><p><strong>Pros:</strong></p><ul><li><p><strong>Reduced Latency:</strong> By pre-loading frequently accessed data into the cache, cache refresh-ahead reduces the latency associated with fetching data from the primary source on demand.</p></li><li><p><strong>Improved Performance:</strong> Proactively populating the cache with data that is likely to be accessed soon improves overall system performance by ensuring that frequently accessed data is readily available in memory.</p></li><li><p><strong>Consistency:</strong> By periodically refreshing pre-loaded data, cache refresh-ahead helps maintain data consistency between the cache and the primary data source, ensuring that cached data remains up-to-date.</p></li></ul></li><li><p><strong>Cons:</strong></p><ul><li><p><strong>Resource Overhead:</strong> Proactive data fetching and cache pre-loading consume additional system resources, such as memory, CPU, and network bandwidth, especially for large or frequently updated data sets.</p></li><li><p><strong>Over-Population:</strong> Inefficient cache pre-loading strategies may lead to over-population of the cache with unnecessary or infrequently accessed data, resulting in wasted resources and reduced cache effectiveness.</p></li></ul></li></ul></li></ul></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!UgCU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F798e5043-1702-46ac-8f3f-3e6800c39f4f_3240x1234.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UgCU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F798e5043-1702-46ac-8f3f-3e6800c39f4f_3240x1234.jpeg 424w, https://substackcdn.com/image/fetch/$s_!UgCU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F798e5043-1702-46ac-8f3f-3e6800c39f4f_3240x1234.jpeg 848w, https://substackcdn.com/image/fetch/$s_!UgCU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F798e5043-1702-46ac-8f3f-3e6800c39f4f_3240x1234.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!UgCU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F798e5043-1702-46ac-8f3f-3e6800c39f4f_3240x1234.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!UgCU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F798e5043-1702-46ac-8f3f-3e6800c39f4f_3240x1234.jpeg" width="1456" height="555" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/798e5043-1702-46ac-8f3f-3e6800c39f4f_3240x1234.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:555,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:157637,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!UgCU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F798e5043-1702-46ac-8f3f-3e6800c39f4f_3240x1234.jpeg 424w, https://substackcdn.com/image/fetch/$s_!UgCU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F798e5043-1702-46ac-8f3f-3e6800c39f4f_3240x1234.jpeg 848w, https://substackcdn.com/image/fetch/$s_!UgCU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F798e5043-1702-46ac-8f3f-3e6800c39f4f_3240x1234.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!UgCU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F798e5043-1702-46ac-8f3f-3e6800c39f4f_3240x1234.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Cache Refresh Ahead Flow</figcaption></figure></div><ul><li><p><strong>Write Strategies</strong></p><ul><li><p><strong>Write Through </strong>- caching strategy where data is written to both the cache and the underlying data store simultaneously whenever a write operation occurs.</p><ul><li><p><strong>Pros:</strong></p><ul><li><p><strong>Data Consistency:</strong> By writing data to both the cache and the underlying data store simultaneously, cache write-through ensures that the cache remains synchronized with the primary data source, minimizing the risk of data inconsistency.</p></li><li><p><strong>Simplicity:</strong> Cache write-through simplifies cache management by eliminating the need for separate cache invalidation or synchronization mechanisms, as data is always written to both the cache and the data store.</p></li></ul></li><li><p><strong>Cons:</strong></p><ul><li><p><strong>Write Latency:</strong> Write operations in cache write-through may experience increased latency due to the additional step of writing data to both the cache and the data store, which can impact application performance, especially for write-heavy workloads.</p></li><li><p><strong>Potential Bottleneck:</strong> In highly concurrent or distributed environments, cache write-through may introduce a potential bottleneck if multiple write operations contend for access to the cache and the data store simultaneously, leading to contention and performance degradation.</p></li></ul></li></ul></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!TcjP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83147e32-a3be-477a-af6d-0c2e971e5396_3270x1222.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!TcjP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83147e32-a3be-477a-af6d-0c2e971e5396_3270x1222.jpeg 424w, https://substackcdn.com/image/fetch/$s_!TcjP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83147e32-a3be-477a-af6d-0c2e971e5396_3270x1222.jpeg 848w, https://substackcdn.com/image/fetch/$s_!TcjP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83147e32-a3be-477a-af6d-0c2e971e5396_3270x1222.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!TcjP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83147e32-a3be-477a-af6d-0c2e971e5396_3270x1222.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!TcjP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83147e32-a3be-477a-af6d-0c2e971e5396_3270x1222.jpeg" width="1456" height="544" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/83147e32-a3be-477a-af6d-0c2e971e5396_3270x1222.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:544,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:112312,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!TcjP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83147e32-a3be-477a-af6d-0c2e971e5396_3270x1222.jpeg 424w, https://substackcdn.com/image/fetch/$s_!TcjP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83147e32-a3be-477a-af6d-0c2e971e5396_3270x1222.jpeg 848w, https://substackcdn.com/image/fetch/$s_!TcjP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83147e32-a3be-477a-af6d-0c2e971e5396_3270x1222.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!TcjP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83147e32-a3be-477a-af6d-0c2e971e5396_3270x1222.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Cache Write Through Flow</figcaption></figure></div><ul><li><p><strong>Write Around</strong> - caching strategy where write operations bypass the cache and are written directly to the underlying data store. Data is cached when it is read from the data store, allowing the cache to store frequently accessed data while avoiding unnecessary caching of infrequently accessed or transient data.</p><ul><li><p><strong>Pros:</strong></p><ul><li><p><strong>Reduced Cache Pollution:</strong> By bypassing the cache for write operations, cache write-around avoids caching infrequently accessed or transient data, reducing cache pollution</p></li><li><p><strong>Scalability:</strong> Cache write-around is well-suited for scenarios with write-heavy workloads or large datasets, as it minimizes the impact on cache performance and storage capacity by avoiding unnecessary caching of write operations.</p></li></ul></li><li><p><strong>Cons:</strong></p><ul><li><p><strong>Read Latency:</strong> The first read operation for data that has not been cached incurs additional latency, as the data must be fetched from the underlying data store instead of the cache, potentially impacting application performance.</p></li><li><p><strong>Stale Data:</strong> If data is frequently updated or modified in the underlying data store, cache write-around may result in cached data becoming stale, as the cache does not proactively invalidate or update cached data based on write operations.</p></li></ul></li></ul></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pCrm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30926e64-76ec-4d38-8240-6c56256c6f16_3265x1224.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pCrm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30926e64-76ec-4d38-8240-6c56256c6f16_3265x1224.jpeg 424w, https://substackcdn.com/image/fetch/$s_!pCrm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30926e64-76ec-4d38-8240-6c56256c6f16_3265x1224.jpeg 848w, https://substackcdn.com/image/fetch/$s_!pCrm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30926e64-76ec-4d38-8240-6c56256c6f16_3265x1224.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!pCrm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30926e64-76ec-4d38-8240-6c56256c6f16_3265x1224.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pCrm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30926e64-76ec-4d38-8240-6c56256c6f16_3265x1224.jpeg" width="1456" height="546" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/30926e64-76ec-4d38-8240-6c56256c6f16_3265x1224.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:546,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:148237,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!pCrm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30926e64-76ec-4d38-8240-6c56256c6f16_3265x1224.jpeg 424w, https://substackcdn.com/image/fetch/$s_!pCrm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30926e64-76ec-4d38-8240-6c56256c6f16_3265x1224.jpeg 848w, https://substackcdn.com/image/fetch/$s_!pCrm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30926e64-76ec-4d38-8240-6c56256c6f16_3265x1224.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!pCrm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F30926e64-76ec-4d38-8240-6c56256c6f16_3265x1224.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Cache Around Write Flow</figcaption></figure></div><ul><li><p><strong>Write Back</strong> - caching strategy where write operations are initially written to the cache and later asynchronously propagated to the underlying data store.</p><ul><li><p><strong>Pros:</strong></p><ul><li><p><strong>Improved Write Performance:</strong> Cache write-back improves write performance by acknowledging write operations as soon as they are written to the cache, without waiting for them to be persisted to the data store. This reduces latency and improves throughput, especially for write-heavy workloads.</p></li><li><p><strong>Optimized Resource Utilization:</strong> Cache write-back optimizes resource utilization by buffering write operations in the cache, allowing the data store to handle write operations more efficiently and effectively, especially during peak load periods.</p></li></ul></li><li><p><strong>Cons:</strong></p><ul><li><p><strong>Increased Complexity:</strong> Implementing cache write-back requires additional mechanisms for asynchronous data propagation, periodic flushing, and handling of failure scenarios, increasing system complexity and maintenance overhead.</p></li><li><p><strong>Potential Data Loss:</strong> In the event of cache failure or system crash, cached data that has not been flushed to the data store may be lost, leading to potential data loss or corruption. Proper backup and recovery mechanisms are required to mitigate this risk.</p></li></ul></li></ul></li></ul></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dm9h!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87be0862-0a6c-4fd7-a741-6bd4d2718e3a_3334x1199.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dm9h!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87be0862-0a6c-4fd7-a741-6bd4d2718e3a_3334x1199.jpeg 424w, https://substackcdn.com/image/fetch/$s_!dm9h!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87be0862-0a6c-4fd7-a741-6bd4d2718e3a_3334x1199.jpeg 848w, https://substackcdn.com/image/fetch/$s_!dm9h!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87be0862-0a6c-4fd7-a741-6bd4d2718e3a_3334x1199.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!dm9h!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87be0862-0a6c-4fd7-a741-6bd4d2718e3a_3334x1199.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dm9h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87be0862-0a6c-4fd7-a741-6bd4d2718e3a_3334x1199.jpeg" width="1456" height="524" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/87be0862-0a6c-4fd7-a741-6bd4d2718e3a_3334x1199.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:524,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:130323,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!dm9h!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87be0862-0a6c-4fd7-a741-6bd4d2718e3a_3334x1199.jpeg 424w, https://substackcdn.com/image/fetch/$s_!dm9h!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87be0862-0a6c-4fd7-a741-6bd4d2718e3a_3334x1199.jpeg 848w, https://substackcdn.com/image/fetch/$s_!dm9h!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87be0862-0a6c-4fd7-a741-6bd4d2718e3a_3334x1199.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!dm9h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F87be0862-0a6c-4fd7-a741-6bd4d2718e3a_3334x1199.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Cache Write Back Flow</figcaption></figure></div><p>Each caching strategy has its own advantages and considerations, and the selection of an appropriate strategy depends on the specific requirements and characteristics of the system.&nbsp;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9cym!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe06d517a-59c2-4bbe-a7e7-c83fc5d46dfa_1912x2091.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9cym!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe06d517a-59c2-4bbe-a7e7-c83fc5d46dfa_1912x2091.jpeg 424w, https://substackcdn.com/image/fetch/$s_!9cym!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe06d517a-59c2-4bbe-a7e7-c83fc5d46dfa_1912x2091.jpeg 848w, https://substackcdn.com/image/fetch/$s_!9cym!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe06d517a-59c2-4bbe-a7e7-c83fc5d46dfa_1912x2091.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!9cym!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe06d517a-59c2-4bbe-a7e7-c83fc5d46dfa_1912x2091.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9cym!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe06d517a-59c2-4bbe-a7e7-c83fc5d46dfa_1912x2091.jpeg" width="1456" height="1592" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e06d517a-59c2-4bbe-a7e7-c83fc5d46dfa_1912x2091.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1592,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:210364,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!9cym!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe06d517a-59c2-4bbe-a7e7-c83fc5d46dfa_1912x2091.jpeg 424w, https://substackcdn.com/image/fetch/$s_!9cym!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe06d517a-59c2-4bbe-a7e7-c83fc5d46dfa_1912x2091.jpeg 848w, https://substackcdn.com/image/fetch/$s_!9cym!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe06d517a-59c2-4bbe-a7e7-c83fc5d46dfa_1912x2091.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!9cym!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe06d517a-59c2-4bbe-a7e7-c83fc5d46dfa_1912x2091.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Caching Read/Write Strategies</figcaption></figure></div><h3>Summary</h3><p>In this article, we've explored the fundamentals of caching, covering the core definition of caching, scenarios where it offers significant advantages, the importance of eviction policies (like LRU or MRU) to manage cache size, and strategies for invalidation to ensure your cache aligns with the primary data source. We also touched on the flow of data between the cache and your database for both read and write operations. </p><p><strong>Stay Tuned!</strong> In upcoming articles, we'll dive deeper into:</p><ul><li><p><strong>Types of Caches:</strong> Exploring different caching mechanisms like in-memory, distributed, and CDN caching.</p></li><li><p><strong>Deployment Strategies:</strong> Understanding how to integrate caching into your architecture.</p></li><li><p><strong>Metrics:</strong> How to monitor cache performance for optimal results.</p></li><li><p><strong>Implementation Solutions:</strong> Practical examples with popular caching tools and libraries.</p></li></ul>]]></content:encoded></item><item><title><![CDATA[Refactoring legacy code: The Strangler Fig Migration Pattern]]></title><description><![CDATA[On one of the approaches for breaking the monolith into microservices]]></description><link>https://blog.diana-enache.com/p/refactoring-legacy-code-the-strangler</link><guid isPermaLink="false">https://blog.diana-enache.com/p/refactoring-legacy-code-the-strangler</guid><dc:creator><![CDATA[Diana Darie]]></dc:creator><pubDate>Fri, 05 Jan 2024 06:48:59 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/906d0708-27e3-46f3-a8f2-65de2ed2f77d_518x426.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_!tNaN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5403a7a9-b2aa-48c4-83f5-d9a488352cb0_13933x5627.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tNaN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5403a7a9-b2aa-48c4-83f5-d9a488352cb0_13933x5627.png 424w, https://substackcdn.com/image/fetch/$s_!tNaN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5403a7a9-b2aa-48c4-83f5-d9a488352cb0_13933x5627.png 848w, https://substackcdn.com/image/fetch/$s_!tNaN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5403a7a9-b2aa-48c4-83f5-d9a488352cb0_13933x5627.png 1272w, https://substackcdn.com/image/fetch/$s_!tNaN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5403a7a9-b2aa-48c4-83f5-d9a488352cb0_13933x5627.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!tNaN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5403a7a9-b2aa-48c4-83f5-d9a488352cb0_13933x5627.png" width="1456" height="588" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5403a7a9-b2aa-48c4-83f5-d9a488352cb0_13933x5627.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:588,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:4494687,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!tNaN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5403a7a9-b2aa-48c4-83f5-d9a488352cb0_13933x5627.png 424w, https://substackcdn.com/image/fetch/$s_!tNaN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5403a7a9-b2aa-48c4-83f5-d9a488352cb0_13933x5627.png 848w, https://substackcdn.com/image/fetch/$s_!tNaN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5403a7a9-b2aa-48c4-83f5-d9a488352cb0_13933x5627.png 1272w, https://substackcdn.com/image/fetch/$s_!tNaN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5403a7a9-b2aa-48c4-83f5-d9a488352cb0_13933x5627.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">Illustrations by <a href="https://storyset.com/">Storyset</a></figcaption></figure></div><p>Microservices have been getting more and more popular in recent years, and several companies are migrating their monolithic applications to microservices. But just a reminder that switching to microservices might not always be the good option. Martin Fowler wrote a nice article regarding the <a href="http://bit.ly/2jclLet">monolith-first approach</a>. Here are a couple of useful statements:</p><ul><li><p><em>Almost all the successful microservice stories have started with a monolith that grew too big and was broken up.</em></p></li><li><p><em>Almost all the cases I&#8217;ve heard of a system that was built as a microservice system from scratch, it has ended up in serious trouble.</em></p></li></ul><p>A migration technique that has been frequently used when doing system rewrites is called the Strangler Fig Application. This migration method is based on incrementally replacing existing functionalities of the old legacy system with new applications and services in a phased approach until the new application system eventually replaces all of the old legacy system&#8217;s features.</p><p>The name of this type of tree, the Strangler Fig, comes from their pattern of growth around the host tree, which often results in the host&#8217;s death. The roots grow down to the forest floor where they take root and begin to take nutrients from the soil. Gradually the roots wrap around the host tree, widen, and slowly form a lattice-work that surrounds the host&#8217;s trunk. The fig&#8217;s crown grows foliage which soon overshadows the tree. Eventually, the host tree dies leaving the fig with a hollow trunk.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8oeS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1a5889a-f447-4899-a9ec-a3b4e229d4fc_1400x509.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8oeS!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1a5889a-f447-4899-a9ec-a3b4e229d4fc_1400x509.png 424w, https://substackcdn.com/image/fetch/$s_!8oeS!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1a5889a-f447-4899-a9ec-a3b4e229d4fc_1400x509.png 848w, https://substackcdn.com/image/fetch/$s_!8oeS!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1a5889a-f447-4899-a9ec-a3b4e229d4fc_1400x509.png 1272w, https://substackcdn.com/image/fetch/$s_!8oeS!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1a5889a-f447-4899-a9ec-a3b4e229d4fc_1400x509.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8oeS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1a5889a-f447-4899-a9ec-a3b4e229d4fc_1400x509.png" width="1400" height="509" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f1a5889a-f447-4899-a9ec-a3b4e229d4fc_1400x509.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:509,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&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_!8oeS!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1a5889a-f447-4899-a9ec-a3b4e229d4fc_1400x509.png 424w, https://substackcdn.com/image/fetch/$s_!8oeS!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1a5889a-f447-4899-a9ec-a3b4e229d4fc_1400x509.png 848w, https://substackcdn.com/image/fetch/$s_!8oeS!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1a5889a-f447-4899-a9ec-a3b4e229d4fc_1400x509.png 1272w, https://substackcdn.com/image/fetch/$s_!8oeS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff1a5889a-f447-4899-a9ec-a3b4e229d4fc_1400x509.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Overview of the growth of the strangler fig tree</figcaption></figure></div><p>Martin Fowler chose this as the name of the pattern as a metaphor of describing a way of doing rewrite of an important system. Our new system is initially supported by and wrapping the existing system. The old and the new can co coexist while the new system can grow and potentially replace the entire old system.</p><blockquote><p>&#8220;An alternative route is to gradually create a new system around the edges of the old, letting it grow slowly over several years until the old system is strangled.&#8221;</p><p>~ Martin Fowler</p></blockquote><h2><strong>Advantages</strong></h2><ul><li><p>It allows for incremental migration to a new system.</p></li><li><p>It allows to pause and even stop the migration while still taking advantage of the new system built so far.</p></li><li><p>Each step is reversible, reducing the risk of each incremental step.</p></li></ul><blockquote><p><em>&#8220;The most important reason to consider a strangler application over a cut-over rewrite is reduced risk. A strangler can give value steadily and the frequent releases allow you to monitor its progress more carefully. Many people still don&#8217;t consider a strangler since they think it will cost more &#8212; I&#8217;m not convinced about that. Since you can use shorter release cycles with a strangler you can avoid a lot of the unnecessary features that cut over rewrites often generate.<strong>&#8221;<br></strong>~ Martin Fowler</em></p></blockquote><h2><strong>When not to use it</strong></h2><ul><li><p>The pattern will not be suitable for small systems where the complexity and size are low.</p></li><li><p>The pattern cannot be used in systems where requests to the back-end system cannot be intercepted and routed.</p></li></ul><h2><strong>Issues</strong></h2><ul><li><p>Considerable effort is required for the legacy and new system integrations.</p></li><li><p>Considerable effort is required for the parallel run of the same functionality.</p></li><li><p>Big commitment. Lack of will and resources to finish the strangling job might lead you into a bigger mess where your system now has two ways of doing everything with an awkward interface between the two.</p></li></ul><h2><strong>How it works</strong></h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5stI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9cae6b2d-c9ae-4ebd-9b3a-ab50521692c1_1400x448.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5stI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9cae6b2d-c9ae-4ebd-9b3a-ab50521692c1_1400x448.png 424w, https://substackcdn.com/image/fetch/$s_!5stI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9cae6b2d-c9ae-4ebd-9b3a-ab50521692c1_1400x448.png 848w, https://substackcdn.com/image/fetch/$s_!5stI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9cae6b2d-c9ae-4ebd-9b3a-ab50521692c1_1400x448.png 1272w, https://substackcdn.com/image/fetch/$s_!5stI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9cae6b2d-c9ae-4ebd-9b3a-ab50521692c1_1400x448.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5stI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9cae6b2d-c9ae-4ebd-9b3a-ab50521692c1_1400x448.png" width="1400" height="448" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9cae6b2d-c9ae-4ebd-9b3a-ab50521692c1_1400x448.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:448,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&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_!5stI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9cae6b2d-c9ae-4ebd-9b3a-ab50521692c1_1400x448.png 424w, https://substackcdn.com/image/fetch/$s_!5stI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9cae6b2d-c9ae-4ebd-9b3a-ab50521692c1_1400x448.png 848w, https://substackcdn.com/image/fetch/$s_!5stI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9cae6b2d-c9ae-4ebd-9b3a-ab50521692c1_1400x448.png 1272w, https://substackcdn.com/image/fetch/$s_!5stI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9cae6b2d-c9ae-4ebd-9b3a-ab50521692c1_1400x448.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Overview of the strangler fig pattern</figcaption></figure></div><p>The strangler fig pattern allows you to move functionality over to your new service without having to touch or make changes to your existing system.</p><p>The pattern involves 4 steps:</p><ul><li><p><strong>Identify </strong>-&gt;<strong> </strong>identify parts of the existing system that you wish to migrate. (use Domain Driven Design to identify the various bounded contexts)</p></li><li><p><strong>Transform </strong>-&gt; implement this functionality in your new microservice.</p></li><li><p><strong>Co-exist</strong> -&gt; leave the existing module in the legacy application as-is. Incrementally reroute calls from the monolith over to the new microservice.</p></li><li><p><strong>Eliminate </strong>-&gt; once the traffic is completely redirected to the microservice, eliminate the legacy module.</p></li></ul><p>First, add a proxy (facade), which sits between the legacy application and the user. This can be a &#8220;bare bones&#8221; routing app or an API Gateway. Initially, this proxy doesn&#8217;t do anything and all the application traffic is routed to the legacy application. Once a new component is built, you can link it to the proxy and you can allow the proxy to serve traffic to that page. You can also test your new functionality in parallel against the existing monolithic code. Keep adding more services and link them to the proxy. Repeat until all required functionality is handled by the new stack. Both the monolith and the new built component need to be functional for a period of time. Sometimes the transitional phase can last for an extended duration. When the new component has been incrementally developed and tested, the legacy monolithic application can be removed.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!TjVe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa9771e6-8f74-4b8a-9a60-7c0a48ddfa3f_1400x713.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!TjVe!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa9771e6-8f74-4b8a-9a60-7c0a48ddfa3f_1400x713.png 424w, https://substackcdn.com/image/fetch/$s_!TjVe!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa9771e6-8f74-4b8a-9a60-7c0a48ddfa3f_1400x713.png 848w, https://substackcdn.com/image/fetch/$s_!TjVe!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa9771e6-8f74-4b8a-9a60-7c0a48ddfa3f_1400x713.png 1272w, https://substackcdn.com/image/fetch/$s_!TjVe!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa9771e6-8f74-4b8a-9a60-7c0a48ddfa3f_1400x713.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!TjVe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa9771e6-8f74-4b8a-9a60-7c0a48ddfa3f_1400x713.png" width="1400" height="713" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fa9771e6-8f74-4b8a-9a60-7c0a48ddfa3f_1400x713.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:713,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&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_!TjVe!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa9771e6-8f74-4b8a-9a60-7c0a48ddfa3f_1400x713.png 424w, https://substackcdn.com/image/fetch/$s_!TjVe!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa9771e6-8f74-4b8a-9a60-7c0a48ddfa3f_1400x713.png 848w, https://substackcdn.com/image/fetch/$s_!TjVe!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa9771e6-8f74-4b8a-9a60-7c0a48ddfa3f_1400x713.png 1272w, https://substackcdn.com/image/fetch/$s_!TjVe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa9771e6-8f74-4b8a-9a60-7c0a48ddfa3f_1400x713.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2><strong>Conclusion</strong></h2><p>Moving from your existing legacy monolithic application into a microserviced architecture is a nice end goal to have but the journey is challenging and needs to be well planned. In this article, we have discussed about the Strangler Fig migration pattern which can help you in your journey. Keep in mind that strangling a monolith is not a quick process and may require some time.</p><h2><strong>Resources</strong></h2><ul><li><p>Martin Fowler <a href="https://www.martinfowler.com/bliki/StranglerApplication.html">Strangler Application</a></p></li><li><p>Michiel Rook <a href="https://www.michielrook.nl/2016/11/strangler-pattern-practice/">The Strangler pattern in practice</a></p></li><li><p>Azure Cloud Patterns <a href="https://docs.microsoft.com/en-us/azure/architecture/patterns/strangler">Strangler pattern</a></p></li></ul>]]></content:encoded></item><item><title><![CDATA[Cracking the System Design Interview]]></title><description><![CDATA[On system design interview format and design components]]></description><link>https://blog.diana-enache.com/p/cracking-the-system-design-interview</link><guid isPermaLink="false">https://blog.diana-enache.com/p/cracking-the-system-design-interview</guid><dc:creator><![CDATA[Diana Darie]]></dc:creator><pubDate>Fri, 29 Dec 2023 07:36:04 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/592c4bf9-b219-43e1-91c9-1fabf8b19405_2000x2000.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_!jVs4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79385945-3948-44b0-a255-7e7652f4729b_13933x5627.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jVs4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79385945-3948-44b0-a255-7e7652f4729b_13933x5627.png 424w, https://substackcdn.com/image/fetch/$s_!jVs4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79385945-3948-44b0-a255-7e7652f4729b_13933x5627.png 848w, https://substackcdn.com/image/fetch/$s_!jVs4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79385945-3948-44b0-a255-7e7652f4729b_13933x5627.png 1272w, https://substackcdn.com/image/fetch/$s_!jVs4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79385945-3948-44b0-a255-7e7652f4729b_13933x5627.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jVs4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79385945-3948-44b0-a255-7e7652f4729b_13933x5627.png" width="1456" height="588" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/79385945-3948-44b0-a255-7e7652f4729b_13933x5627.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:588,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2903292,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!jVs4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79385945-3948-44b0-a255-7e7652f4729b_13933x5627.png 424w, https://substackcdn.com/image/fetch/$s_!jVs4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79385945-3948-44b0-a255-7e7652f4729b_13933x5627.png 848w, https://substackcdn.com/image/fetch/$s_!jVs4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79385945-3948-44b0-a255-7e7652f4729b_13933x5627.png 1272w, https://substackcdn.com/image/fetch/$s_!jVs4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79385945-3948-44b0-a255-7e7652f4729b_13933x5627.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">Illustrations by <a href="https://storyset.com/">Storyset</a></figcaption></figure></div><p>System design interviews are in general 45&#8211;60 minutes long where you are given a broad topic like &#8220;Design Twitter&#8221;. You&#8217;ll be expected to generate a high-level design, showing the different system components that will be required, how they&#8217;re connected, and any trade-offs in the approach you&#8217;ve taken. Time permitting, the interviewers will ask you to go deeper into how some of your system components would function and talk about how you would handle several scenarios and edge cases.</p><p>For a junior, mid-level engineer, this article aims to give you a fair good start at the System Design Interview and it&#8217;s not an exhausting list since system design is a vast topic. But from here, you can dig deeper with other resources.</p><p>Before starting with the theory basics, let&#8217;s briefly talk about how you should approach the interview.</p><ol><li><p><strong>Understand the goal and requirements.<br></strong>Never go head-first into the design, make sure you understand the problem and ask clarifying questions &#8212; What is the goal of the system? Who are the users of the system? What do they need it for? How are they going to use it? Clarify your assumptions.</p></li><li><p><strong>Establish the scope<br></strong>Go through all the features of the system that you can think of and write them down.</p></li><li><p><strong>Establish the scale<br></strong>What is the scale of the system? How many customers does the system need to serve per day? How many transactions? What are the performance requirements (e.g. latency, throughput, availability)? What is the expected read-to-write ratio? What&#8217;s the average expected response time?</p></li><li><p><strong>Design high-level. </strong>The first 20 min of the interview you should have a draft of your high level design. Make sure to discuss the trade offs and why you chose those types of technologies. What type of database would you use and why? What caching solutions are out there? Which would you choose and why?</p></li><li><p><strong>Drill-down</strong>. You should drill-down into more details, starting with the components that you are most familiar with. This is to ensure that you have time to go in-depth into the topics you have the most knowledge in.</p></li><li><p><strong>Wrap-up. </strong>Before the end of your interview, you should spend some time to summarize your solution and highlight important bottlenecks or improvement opportunities.</p><div><hr></div></li></ol><p>Now let&#8217;s touch onto the most encountered components you&#8217;ll probably have to talk about.</p><h1><strong>Distributed Systems</strong></h1><p><em>= group of computers working together as to appear as a single computer to the end-user. They have a shared state, operate concurrently and can fail independently without affecting the whole system&#8217;s uptime.</em></p><p><strong>Key Characteristics:</strong></p><ul><li><p><strong>Stability</strong> or <strong>Serviceability</strong> or <strong>Manageability</strong> = s<em>implicity and speed with which a system can be repaired or maintained.</em></p></li><li><p><strong>Reliability</strong> <em>= probability a system will fail in a given period</em>. A distributed system is considered reliable if it keeps delivering its services even when one or several of its software or hardware components fail.</p></li><li><p><strong>Scalability</strong> <em>=</em> <em>capability of a system, process, or a network to grow and manage increased demand.</em></p></li><li><p><strong>Efficiency/Performance</strong> = <em>response time</em> (or latency = delay to obtain the first item) + <em>throughput</em> (or bandwidth = the number of items delivered in a given time unit)</p></li><li><p><strong>Availability</strong> = <em>simple measure of the percentage of time that a system, service, or a machine remains operational under normal conditions.</em></p></li><li><p><strong>Fault tolerance</strong> and <strong>Catastrophe-preparedness</strong></p></li></ul><h1><strong>Load Balancer</strong></h1><p><em>= component that acts as a reverse proxy and distributes network or application traffic across a number of servers to improve responsiveness and availability of applications, websites or databases.</em></p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ig8Z!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40e06188-c0e3-4f8e-be29-93212fa17e23_1400x296.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ig8Z!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40e06188-c0e3-4f8e-be29-93212fa17e23_1400x296.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Ig8Z!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40e06188-c0e3-4f8e-be29-93212fa17e23_1400x296.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Ig8Z!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40e06188-c0e3-4f8e-be29-93212fa17e23_1400x296.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Ig8Z!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40e06188-c0e3-4f8e-be29-93212fa17e23_1400x296.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ig8Z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40e06188-c0e3-4f8e-be29-93212fa17e23_1400x296.jpeg" width="1400" height="296" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/40e06188-c0e3-4f8e-be29-93212fa17e23_1400x296.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:296,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&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_!Ig8Z!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40e06188-c0e3-4f8e-be29-93212fa17e23_1400x296.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Ig8Z!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40e06188-c0e3-4f8e-be29-93212fa17e23_1400x296.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Ig8Z!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40e06188-c0e3-4f8e-be29-93212fa17e23_1400x296.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Ig8Z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40e06188-c0e3-4f8e-be29-93212fa17e23_1400x296.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><ul><li><p><strong>Benefits</strong>: faster, uninterrupted service, less downtime and higher throughput, predictive analytics that predict traffic bottlenecks (smart LB), fewer failed or stressed components.</p></li></ul><p><strong>Algorithms (used to balance the load):</strong></p><ul><li><p><strong>Least Connection Method</strong> (directs traffic to the server with the fewest active connections)</p></li><li><p><strong>Least Response Time Method</strong> (directs traffic to the server with the fewest active connections)</p></li><li><p><strong>Least Bandwidth Method</strong> (selects the server that is currently serving the least amount of traffic)</p></li><li><p><strong>Round Robin Method</strong> (cycles through a list of servers and sends each new request to the next server)</p></li><li><p><strong>Weighted Round Robin Method</strong> (servers with higher weights (= an integer value that indicates the processing capacity) receive new and more connections before those with less weights) &#8212; to handle servers with different characteristics (e.g. processing power, availability, load)</p></li><li><p><strong>IP Hash</strong> (a hash of the IP address of the client is calculated to redirect the request to a server)</p></li></ul><h1><strong>Caching</strong></h1><p><em>= temporary storage area that stores the result of expensive responses or frequently accessed data in memory so that subsequent requests are served more quickly.</em></p><p><strong>When to use it</strong> &#8212; when data is read frequently but modified infrequently</p><p><strong>Considerations</strong>:</p><ul><li><p>Set an <strong>expiration policy </strong>that is not too short (as it reloads data too fast from the database) and not too long (since data can become stale).</p></li><li><p>How to keep the cache and database <strong>consistent</strong> (see the <em>cache invalidation</em> section below)</p></li><li><p>The cache can easily become a<strong> single point of failure, </strong>you might need to use multiple caches</p></li><li><p>Choose an <strong>eviction policy </strong>(see the <em>cache eviction policies </em>section below)</p></li><li><p>Think how you handle <strong>concurrency </strong>(aka the reader-writer problem) &#8212; When multiple clients are trying to update the cache at the same time, there can be conflicts. A solution would be to use<strong> commit logs</strong>. To update the cache, we can store all the mutations into logs rather than update immediately. And then some background processes will execute all the logs asynchronously. This strategy is commonly adopted in database design.</p></li></ul><p><strong>Reading from cache:</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FC2Y!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99f8dec8-1855-49bf-8e57-0734425933db_1400x731.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FC2Y!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99f8dec8-1855-49bf-8e57-0734425933db_1400x731.jpeg 424w, https://substackcdn.com/image/fetch/$s_!FC2Y!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99f8dec8-1855-49bf-8e57-0734425933db_1400x731.jpeg 848w, https://substackcdn.com/image/fetch/$s_!FC2Y!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99f8dec8-1855-49bf-8e57-0734425933db_1400x731.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!FC2Y!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99f8dec8-1855-49bf-8e57-0734425933db_1400x731.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!FC2Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99f8dec8-1855-49bf-8e57-0734425933db_1400x731.jpeg" width="618" height="322.6842857142857" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/99f8dec8-1855-49bf-8e57-0734425933db_1400x731.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:731,&quot;width&quot;:1400,&quot;resizeWidth&quot;:618,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&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_!FC2Y!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99f8dec8-1855-49bf-8e57-0734425933db_1400x731.jpeg 424w, https://substackcdn.com/image/fetch/$s_!FC2Y!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99f8dec8-1855-49bf-8e57-0734425933db_1400x731.jpeg 848w, https://substackcdn.com/image/fetch/$s_!FC2Y!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99f8dec8-1855-49bf-8e57-0734425933db_1400x731.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!FC2Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99f8dec8-1855-49bf-8e57-0734425933db_1400x731.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Cache Invalidation </strong>= happens when data is modified in the database and becomes inconsistent with the cache.</p><p><strong>Updating the cache:</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!lhkK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b077adc-8bf1-4a81-8e71-5b5feec8fb70_2364x602.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lhkK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b077adc-8bf1-4a81-8e71-5b5feec8fb70_2364x602.png 424w, https://substackcdn.com/image/fetch/$s_!lhkK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b077adc-8bf1-4a81-8e71-5b5feec8fb70_2364x602.png 848w, https://substackcdn.com/image/fetch/$s_!lhkK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b077adc-8bf1-4a81-8e71-5b5feec8fb70_2364x602.png 1272w, https://substackcdn.com/image/fetch/$s_!lhkK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b077adc-8bf1-4a81-8e71-5b5feec8fb70_2364x602.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!lhkK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b077adc-8bf1-4a81-8e71-5b5feec8fb70_2364x602.png" width="1456" height="371" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3b077adc-8bf1-4a81-8e71-5b5feec8fb70_2364x602.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:371,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:242961,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!lhkK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b077adc-8bf1-4a81-8e71-5b5feec8fb70_2364x602.png 424w, https://substackcdn.com/image/fetch/$s_!lhkK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b077adc-8bf1-4a81-8e71-5b5feec8fb70_2364x602.png 848w, https://substackcdn.com/image/fetch/$s_!lhkK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b077adc-8bf1-4a81-8e71-5b5feec8fb70_2364x602.png 1272w, https://substackcdn.com/image/fetch/$s_!lhkK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b077adc-8bf1-4a81-8e71-5b5feec8fb70_2364x602.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><ul><li><p><strong>Write-aside cache</strong> &#8212; data is written into the cache and the corresponding database at the same time (also known as <em>lazy loading</em>) &#8212; cons: higher latency</p></li><li><p><strong>Write-through cache </strong>&#8212; application adds or updates an entry in the cache. Cache synchronously writes entry to the data store. Cache returns the data to the application.</p></li><li><p><strong>Write-around cache</strong> &#8212; data is written directly to permanent storage, bypassing the cache &#8212; cons: read request for recently written data will create a &#8220;cache miss&#8221;.</p></li><li><p><strong>Write-back cache</strong> &#8212; data is written to cache alone and completion is immediately confirmed to the client and then data is <em>asynchronously </em>updated to the data store &#8212; pros: low latency and high throughput; cons: risk of data loss in case of a crash</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xdli!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bdf576c-c8df-4a20-b725-29f050aaea1a_1400x579.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xdli!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bdf576c-c8df-4a20-b725-29f050aaea1a_1400x579.jpeg 424w, https://substackcdn.com/image/fetch/$s_!xdli!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bdf576c-c8df-4a20-b725-29f050aaea1a_1400x579.jpeg 848w, https://substackcdn.com/image/fetch/$s_!xdli!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bdf576c-c8df-4a20-b725-29f050aaea1a_1400x579.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!xdli!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bdf576c-c8df-4a20-b725-29f050aaea1a_1400x579.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xdli!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bdf576c-c8df-4a20-b725-29f050aaea1a_1400x579.jpeg" width="668" height="276.2657142857143" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8bdf576c-c8df-4a20-b725-29f050aaea1a_1400x579.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:579,&quot;width&quot;:1400,&quot;resizeWidth&quot;:668,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&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_!xdli!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bdf576c-c8df-4a20-b725-29f050aaea1a_1400x579.jpeg 424w, https://substackcdn.com/image/fetch/$s_!xdli!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bdf576c-c8df-4a20-b725-29f050aaea1a_1400x579.jpeg 848w, https://substackcdn.com/image/fetch/$s_!xdli!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bdf576c-c8df-4a20-b725-29f050aaea1a_1400x579.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!xdli!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8bdf576c-c8df-4a20-b725-29f050aaea1a_1400x579.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2><strong>Cache eviction policies</strong></h2><ul><li><p><strong>First In First Out (FIFO)</strong> &#8212; evicts the first block accessed first</p></li><li><p><strong>Last In First Out (LIFO)</strong> &#8212; evicts the block accessed most recently</p></li><li><p><strong>Least Recently Used (LRU)</strong> &#8212; evicts the least recently used items first. When the client requests resource A, it happens as follow:<br>If A exists in the cache, we just return immediately.<br>If not and the cache has extra storage slots, we fetch resource A and return to the client. In addition, insert A into the cache.<br>If the cache is full, we kick out the resource that is least recently used and replace it with resource A.</p></li><li><p><strong>Most Recently Used (MRU)</strong> &#8212; evicts the most recently used items first</p></li><li><p><strong>Least Frequently Used (LFU)</strong> &#8212; counts how often an item is needed. Those that are used least often are discarded first.</p></li><li><p><strong>Random Replacement (RR)</strong> &#8212; randomly evicts a candidate item</p></li></ul><p><strong>Concurrency &#8212; reader-writer problem</strong> &#8212; When multiple clients are trying to update the cache at the same time, there can be conflicts. =&gt; use <strong>commit logs</strong>. To update the cache, we can store all the mutations into logs rather than update immediately. And then some background processes will execute all the logs asynchronously. This strategy is commonly adopted in database design.</p><h2><strong>Content Distribution Network (CDN)</strong></h2><p>= <em>system of distributed servers (network) that deliver webpages and other web content to a user based on the geographic locations of the user, the origin of the webpage and a content delivery server.</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!956V!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdba41f3e-a09c-4cba-b594-50e736ef341d_1400x353.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!956V!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdba41f3e-a09c-4cba-b594-50e736ef341d_1400x353.jpeg 424w, https://substackcdn.com/image/fetch/$s_!956V!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdba41f3e-a09c-4cba-b594-50e736ef341d_1400x353.jpeg 848w, https://substackcdn.com/image/fetch/$s_!956V!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdba41f3e-a09c-4cba-b594-50e736ef341d_1400x353.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!956V!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdba41f3e-a09c-4cba-b594-50e736ef341d_1400x353.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!956V!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdba41f3e-a09c-4cba-b594-50e736ef341d_1400x353.jpeg" width="1400" height="353" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dba41f3e-a09c-4cba-b594-50e736ef341d_1400x353.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:353,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&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_!956V!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdba41f3e-a09c-4cba-b594-50e736ef341d_1400x353.jpeg 424w, https://substackcdn.com/image/fetch/$s_!956V!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdba41f3e-a09c-4cba-b594-50e736ef341d_1400x353.jpeg 848w, https://substackcdn.com/image/fetch/$s_!956V!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdba41f3e-a09c-4cba-b594-50e736ef341d_1400x353.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!956V!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdba41f3e-a09c-4cba-b594-50e736ef341d_1400x353.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>System flow</strong>: a request will first ask the CDN for a piece of static media; the CDN will serve that content if it has it locally available. If it isn&#8217;t available, the CDN will query the back-end servers for the file, cache it locally, and serve it to the requesting user.</p><h1><strong>Message Queues</strong></h1><p><em>= durable component, stored in memory, that supports asynchronous communication. Helps reduce request times for expensive operations that would otherwise be performed in-line. Receives, holds, and delivers messages.</em></p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dwLy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c9f14bf-5473-4a40-a9fb-30075bac19a0_1400x490.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dwLy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c9f14bf-5473-4a40-a9fb-30075bac19a0_1400x490.jpeg 424w, https://substackcdn.com/image/fetch/$s_!dwLy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c9f14bf-5473-4a40-a9fb-30075bac19a0_1400x490.jpeg 848w, https://substackcdn.com/image/fetch/$s_!dwLy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c9f14bf-5473-4a40-a9fb-30075bac19a0_1400x490.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!dwLy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c9f14bf-5473-4a40-a9fb-30075bac19a0_1400x490.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dwLy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c9f14bf-5473-4a40-a9fb-30075bac19a0_1400x490.jpeg" width="650" height="227.5" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7c9f14bf-5473-4a40-a9fb-30075bac19a0_1400x490.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:490,&quot;width&quot;:1400,&quot;resizeWidth&quot;:650,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&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_!dwLy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c9f14bf-5473-4a40-a9fb-30075bac19a0_1400x490.jpeg 424w, https://substackcdn.com/image/fetch/$s_!dwLy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c9f14bf-5473-4a40-a9fb-30075bac19a0_1400x490.jpeg 848w, https://substackcdn.com/image/fetch/$s_!dwLy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c9f14bf-5473-4a40-a9fb-30075bac19a0_1400x490.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!dwLy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c9f14bf-5473-4a40-a9fb-30075bac19a0_1400x490.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>If an operation is too slow to perform inline, you can use a message queue with the following workflow:</p><ul><li><p>An application publishes a job to the queue, then notifies the user of job status.</p></li><li><p>A worker picks up the job from the queue, processes it, then signals the job is complete.</p></li></ul><p>e.g. RabbitMQ, Amazon SQS</p><h1><strong>Proxies</strong></h1><p><em>= piece of software or hardware that acts as an intermediary for requests from clients seeking resources from other servers</em>.</p><ul><li><p>used to filter requests, log requests, or sometimes transform requests. Its cache can serve a lot of requests (If multiple clients access a particular resource, the proxy server can cache it and serve it to all the clients without going to the remote server.)</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2fA0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fea6f4a-2bc3-4a96-b45c-08dd0b3858a8_1400x640.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2fA0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fea6f4a-2bc3-4a96-b45c-08dd0b3858a8_1400x640.jpeg 424w, https://substackcdn.com/image/fetch/$s_!2fA0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fea6f4a-2bc3-4a96-b45c-08dd0b3858a8_1400x640.jpeg 848w, https://substackcdn.com/image/fetch/$s_!2fA0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fea6f4a-2bc3-4a96-b45c-08dd0b3858a8_1400x640.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!2fA0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fea6f4a-2bc3-4a96-b45c-08dd0b3858a8_1400x640.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2fA0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fea6f4a-2bc3-4a96-b45c-08dd0b3858a8_1400x640.jpeg" width="594" height="271.54285714285714" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5fea6f4a-2bc3-4a96-b45c-08dd0b3858a8_1400x640.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:640,&quot;width&quot;:1400,&quot;resizeWidth&quot;:594,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&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_!2fA0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fea6f4a-2bc3-4a96-b45c-08dd0b3858a8_1400x640.jpeg 424w, https://substackcdn.com/image/fetch/$s_!2fA0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fea6f4a-2bc3-4a96-b45c-08dd0b3858a8_1400x640.jpeg 848w, https://substackcdn.com/image/fetch/$s_!2fA0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fea6f4a-2bc3-4a96-b45c-08dd0b3858a8_1400x640.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!2fA0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5fea6f4a-2bc3-4a96-b45c-08dd0b3858a8_1400x640.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Types</strong>:</p><ul><li><p><strong>Open Proxy</strong> &#8212; accessible by any Internet user. Allows users within a network group to store and forward Internet services such as DNS or web pages to reduce and control the bandwidth used by the group.</p></li></ul><p><strong>Anonymous Proxy</strong> &#8212; reveals &#1110;ts &#1110;dent&#1110;ty &#1072;s &#1072; server but does not disclose the &#1110;n&#1110;t&#1110;&#1072;l IP address</p><p><strong>Tr&#1072;nsp&#1072;rent Proxy </strong>&#8212; &#1110;dent&#1110;f&#1110;es &#1110;tself, &#1072;nd w&#1110;th the support of HTTP he&#1072;ders, the f&#1110;rst IP &#1072;ddress c&#1072;n be v&#1110;ewed.</p><ul><li><p><strong>Reverse Proxy</strong> &#8212; retrieves resources on behalf of a client from one or more servers</p></li></ul><h1><strong>Databases</strong></h1><h2><strong>SQL vs NoSQL</strong></h2><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/RJVNG/2/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/17b80096-5d24-4809-8b7a-ba5d956c0961_1260x660.png&quot;,&quot;thumbnail_url_full&quot;:&quot;&quot;,&quot;height&quot;:992,&quot;title&quot;:&quot;SQL vs NoSQL&quot;,&quot;description&quot;:&quot;&quot;}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/RJVNG/2/" width="730" height="992" frameborder="0" scrolling="no"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><p></p><h2><strong>NoSQL Types</strong></h2><div id="datawrapper-iframe" class="datawrapper-wrap outer" data-attrs="{&quot;url&quot;:&quot;https://datawrapper.dwcdn.net/W3gm8/1/&quot;,&quot;thumbnail_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/53d3b357-c75e-45f3-a6fe-8f48a3b3f64e_1260x660.png&quot;,&quot;thumbnail_url_full&quot;:&quot;&quot;,&quot;height&quot;:743,&quot;title&quot;:&quot;NoSQL Types&quot;,&quot;description&quot;:&quot;&quot;}" data-component-name="DatawrapperToDOM"><iframe id="iframe-datawrapper" class="datawrapper-iframe" src="https://datawrapper.dwcdn.net/W3gm8/1/" width="730" height="743" frameborder="0" scrolling="no"></iframe><script type="text/javascript">!function(){"use strict";window.addEventListener("message",(function(e){if(void 0!==e.data["datawrapper-height"]){var t=document.querySelectorAll("iframe");for(var a in e.data["datawrapper-height"])for(var r=0;r<t.length;r++){if(t[r].contentWindow===e.source)t[r].style.height=e.data["datawrapper-height"][a]+"px"}}}))}();</script></div><h2><strong>Sharding or Data Partitioning</strong></h2><p><em>= process of splitting up a DB/table across multiple machines to improve the manageability, performance, availability, and load balancing of an application</em></p><p><strong>Partitioning Methods:</strong></p><ul><li><p><strong>Horizontal Partitioning</strong> &#8212; put different rows into different tables &#8212; <strong>cons</strong>: unbalanced servers (if the value whose range is used for sharding isn&#8217;t chosen carefully)</p></li><li><p><strong>Vertical Partitioning</strong> divide our data to store tables related to a specific feature in their own server (instagram use case &#8212; user profile information stored on one DB server, friend lists on another) &#8212; <strong>cons</strong>: if our application experiences additional growth, then it may be necessary to further partition a feature specific DB across various servers</p></li><li><p><strong>Directory Based Partitioning</strong> &#8212; create a lookup service which knows your current partitioning scheme and abstracts it away from the DB access code.</p></li></ul><p><strong>Partitioning Criteria:</strong></p><ul><li><p><strong>Key or Hash-based partitioning</strong> &#8212; apply a hash function to some key attributes of the entity we are storing &#8212; <strong>cons</strong>: adding new servers means changing the hash function which would require redistribution of data and downtime for the service. (use Consistent Hashing)</p></li><li><p><strong>List partitioning</strong> &#8212; each partition is assigned a list of values, so whenever we want to insert a new record, we will see which partition contains our key and then store it there</p></li><li><p><strong>Round-robin partitioning</strong> &#8212; With &#8217;n&#8217; partitions, the &#8216;i&#8217; tuple is assigned to partition (i mod n).</p></li><li><p><strong>Composite partitioning</strong> &#8212; combine any of the above partitioning schemes to devise a new scheme</p></li></ul><p><strong>Complexities:</strong></p><p><strong>Joins and Denormalization</strong> &#8212; not feasible to perform joins that span database shards (denormalize the database so that queries that previously required joins can be performed from a single table)</p><p><strong>Referential Integrity</strong> &#8212; enforcing foreign keys in a sharded database can be extremely difficult. (not supported by most RDBMS &#8212; has to be enforced in application code.)</p><p><strong>Celebrity problem</strong> &#8212; how would you deal with hotspots? (one way would be to add a shard for each celebrity)</p><p><strong>Rebalancing/Resharding</strong> &#8212; data distribution is not uniform and there is a lot of load on a shard =&gt; have to create more DB shards or have to rebalance existing shards.</p><p><strong>Strategies</strong>:</p><ul><li><p><strong>Fixed number of partitions</strong> &#8212; Create many more partitions than there are nodes, and assign several partitions to each node</p></li><li><p><strong>Dynamic partitioning</strong> &#8212; when a partition grows to exceed a configured size, it is split into 2 partitions so that approximately half of the data ends up on each side of the split (no of partitions adapt to the total data volume)</p></li><li><p><strong>Partitioning proportionally to nodes</strong> &#8212; have a fixed no of partitions per node. The size of each partition grows proportionally to the dataset size while the no of nodes remains unchanged</p></li></ul><p>Examples of Real World Scenarios:</p><ul><li><p><em><strong><a href="https://medium.com/tinder-engineering/geosharded-recommendations-part-1-sharding-approach-d5d54e0ec77a">Read about Tinder&#8217;s Geosharded Recommendations Part 1: Sharding Approach</a> </strong>&#8212; </em>Based on Google&#8217;s S2 which uses the <strong>Hilbert curve </strong>(<em>=a space-filling curve that preserves spatial locality: two points that are close on the Hilbert curve are close in physical space. Each smallest Hilbert curve clone is a cell, and 4 adjacent cells form a bigger cell.</em>) Create the geoshards by enumerating all the possible container sizes, and calculate the standard deviation of each sharding configuration, the one with smallest standard deviation will be the most balanced geo sharding configuration we are looking for.</p></li><li><p><em><strong><a href="https://medium.com/@buckhx/unwinding-uber-s-most-efficient-service-406413c5871d">Read about Uber&#8217;s Unwinding Uber&#8217;s Most Efficient Service</a> </strong>&#8212; </em>using a QuadTree &#8212; Take a flat projection of your search space and divide it into quarters that we&#8217;ll call cells. You then divide each of those cells into quarters recursively until you hit a defined maximum depth which will be the leaves of the tree.</p></li><li><p><em><strong><a href="https://instagram-engineering.com/sharding-ids-at-instagram-1cf5a71e5a5c">Read about Instragram&#8217;s Sharding &amp; IDs at Instagram</a></strong></em></p></li></ul><h1><strong>Replication</strong></h1><p><em>= keeping a copy of the same data on multiple machines that are connected via a network.</em></p><p><strong>Reasons</strong>:</p><ul><li><p><strong>Latency</strong> &#8212; Keep data geographically close to your users (reduce access latency)</p></li><li><p>High <strong>availability</strong> &#8212; Allow the system to continue working even if some parts of it have failed</p></li><li><p><strong>Scalability</strong> &#8212; Scale out the number of machines that can serve read queries</p></li></ul><p><strong>Leader-based replication</strong>:</p><ul><li><p>One of the replicas is designated as the <strong>leader</strong>. When clients want to write to DB, they send their requests to the leader, which writes the data to its local storage</p></li><li><p>The other replicas (<strong>followers</strong>) receive the data from the leader in a process called <strong>replication log</strong> or <strong>change stream</strong>.</p></li><li><p>When a client wants to read from the DB, it can query both leader/any of the followers.</p></li></ul><h1><strong>Indexes</strong></h1><p><em>= data structure that improves the speed of data retrieval operations on a database table at the cost of additional writes and storage space to maintain the index data structure.</em></p><p>Can be created using one or more columns of a database table.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1xDW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff99d4b71-e9e4-4b74-9c12-c59d7187f247_1400x694.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1xDW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff99d4b71-e9e4-4b74-9c12-c59d7187f247_1400x694.jpeg 424w, https://substackcdn.com/image/fetch/$s_!1xDW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff99d4b71-e9e4-4b74-9c12-c59d7187f247_1400x694.jpeg 848w, https://substackcdn.com/image/fetch/$s_!1xDW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff99d4b71-e9e4-4b74-9c12-c59d7187f247_1400x694.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!1xDW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff99d4b71-e9e4-4b74-9c12-c59d7187f247_1400x694.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1xDW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff99d4b71-e9e4-4b74-9c12-c59d7187f247_1400x694.jpeg" width="1400" height="694" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f99d4b71-e9e4-4b74-9c12-c59d7187f247_1400x694.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:694,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&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_!1xDW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff99d4b71-e9e4-4b74-9c12-c59d7187f247_1400x694.jpeg 424w, https://substackcdn.com/image/fetch/$s_!1xDW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff99d4b71-e9e4-4b74-9c12-c59d7187f247_1400x694.jpeg 848w, https://substackcdn.com/image/fetch/$s_!1xDW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff99d4b71-e9e4-4b74-9c12-c59d7187f247_1400x694.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!1xDW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff99d4b71-e9e4-4b74-9c12-c59d7187f247_1400x694.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h1><strong>ACID</strong></h1><p><em>= set of properties of database transactions intended to guarantee validity even in the event of errors, power failures, etc</em>.</p><p>In the context of databases, a sequence of database operations that satisfies the ACID properties (and these can be perceived as a single logical operation on the data) is called a <strong>transaction</strong>. For example, a transfer of funds from one bank account to another, even involving multiple changes such as debiting one account and crediting another, is a single transaction.</p><p><strong>Atomicity</strong> &#8212; means that you guarantee that either all of the transaction succeeds or none of it does. You don&#8217;t get part of it succeeding and part of it not. If one part of the transaction fails, the whole transaction fails. With atomicity, it&#8217;s either &#8220;all or nothing&#8221;.</p><p><strong>Consistency</strong> &#8212; this ensures that you guarantee that all data will be consistent. All data will be valid according to all defined rules, including any constraints, cascades, and triggers that have been applied on the database.</p><p><strong>Isolation</strong> &#8212; guarantees that all transactions will occur in isolation. No transaction will be affected by any other transaction. So a transaction cannot read data from any other transaction that has not yet completed.</p><p><strong>Durability</strong> &#8212; means that, once a transaction is committed, it will remain in the system &#8212; even if there&#8217;s a system crash immediately following the transaction. Any changes from the transaction must be stored permanently. If the system tells the user that the transaction has succeeded, the transaction must have, in fact, succeeded.</p><h1><strong>CAP</strong></h1><p><em>impossible for a distributed software system to simultaneously provide more than two out of three of the following guarantees (CAP): Consistency, Availability, and Partition tolerance</em></p><ul><li><p><strong>Consistency</strong>: All nodes see the same data at the same time. Consistency is achieved by updating several nodes before allowing further reads.</p></li><li><p><strong>Availability</strong>: Every request gets a response on success/failure. Availability is achieved by replicating the data across different servers.</p></li><li><p><strong>Partition tolerance:</strong> The system continues to work despite message loss or partial failure. Means that the cluster continues to function even if there is a &#8220;partition&#8221; (communication break) between two nodes (both nodes are up, but can&#8217;t communicate).</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Zsjc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7eb2e670-14f9-405f-91aa-aa7a47acd82e_1400x819.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Zsjc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7eb2e670-14f9-405f-91aa-aa7a47acd82e_1400x819.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Zsjc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7eb2e670-14f9-405f-91aa-aa7a47acd82e_1400x819.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Zsjc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7eb2e670-14f9-405f-91aa-aa7a47acd82e_1400x819.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Zsjc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7eb2e670-14f9-405f-91aa-aa7a47acd82e_1400x819.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Zsjc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7eb2e670-14f9-405f-91aa-aa7a47acd82e_1400x819.jpeg" width="1400" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7eb2e670-14f9-405f-91aa-aa7a47acd82e_1400x819.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1400,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&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_!Zsjc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7eb2e670-14f9-405f-91aa-aa7a47acd82e_1400x819.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Zsjc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7eb2e670-14f9-405f-91aa-aa7a47acd82e_1400x819.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Zsjc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7eb2e670-14f9-405f-91aa-aa7a47acd82e_1400x819.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Zsjc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7eb2e670-14f9-405f-91aa-aa7a47acd82e_1400x819.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>All the combinations available are:</p><ul><li><p><strong>CA</strong> &#8212; data is consistent between all nodes &#8212; as long as all nodes are online &#8212; and you can read/write from any node and be sure that the data is the same, but if you ever develop a partition between nodes, the data will be out of sync (and won&#8217;t re-sync once the partition is resolved).</p></li><li><p><strong>CP</strong> &#8212; data is consistent between all nodes, and maintains partition tolerance (preventing data desync) by becoming unavailable when a node goes down.</p></li><li><p><strong>AP</strong> &#8212; nodes remain online even if they can&#8217;t communicate with each other and will resync data once the partition is resolved, but you aren&#8217;t guaranteed that all nodes will have the same data (either during or after the partition)</p><div><hr></div></li></ul><h1><strong>Conclusion</strong></h1><p>I hope this article can be the first stepping stone on your journey to ace your system design interview. Good luck and reach out for any questions or feedback &#128515;</p>]]></content:encoded></item><item><title><![CDATA[Optimising Performance: The Cool Magic of Bloom Filters]]></title><description><![CDATA[This is the first part of a System Design Patterns series where we dive into a system design problem and present possible ways to approach it.]]></description><link>https://blog.diana-enache.com/p/optimising-performance-the-cool-magic</link><guid isPermaLink="false">https://blog.diana-enache.com/p/optimising-performance-the-cool-magic</guid><dc:creator><![CDATA[Diana Darie]]></dc:creator><pubDate>Thu, 09 Nov 2023 15:56:10 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/334eb984-74ff-4795-8d8f-6f9c29df2030_1722x942.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_!_gee!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45e1a8c9-b6c4-43f2-ae65-c31491d0bc52_14002x5697.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_gee!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45e1a8c9-b6c4-43f2-ae65-c31491d0bc52_14002x5697.png 424w, https://substackcdn.com/image/fetch/$s_!_gee!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45e1a8c9-b6c4-43f2-ae65-c31491d0bc52_14002x5697.png 848w, https://substackcdn.com/image/fetch/$s_!_gee!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45e1a8c9-b6c4-43f2-ae65-c31491d0bc52_14002x5697.png 1272w, https://substackcdn.com/image/fetch/$s_!_gee!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45e1a8c9-b6c4-43f2-ae65-c31491d0bc52_14002x5697.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_gee!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45e1a8c9-b6c4-43f2-ae65-c31491d0bc52_14002x5697.png" width="1456" height="592" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/45e1a8c9-b6c4-43f2-ae65-c31491d0bc52_14002x5697.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:592,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2223822,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!_gee!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45e1a8c9-b6c4-43f2-ae65-c31491d0bc52_14002x5697.png 424w, https://substackcdn.com/image/fetch/$s_!_gee!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45e1a8c9-b6c4-43f2-ae65-c31491d0bc52_14002x5697.png 848w, https://substackcdn.com/image/fetch/$s_!_gee!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45e1a8c9-b6c4-43f2-ae65-c31491d0bc52_14002x5697.png 1272w, https://substackcdn.com/image/fetch/$s_!_gee!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45e1a8c9-b6c4-43f2-ae65-c31491d0bc52_14002x5697.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">Illustrations by <a href="https://storyset.com/">Storyset</a></figcaption></figure></div><h3>Motivation</h3><p>When you have a large set of structured data (identified by record IDs) stored in a set of data files, what is the most efficient way to know which file might contain our required data? We need to keep track of large entities with the smallest memory print possible.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.diana-enache.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Diana&#8217;s Substack! 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>Reading each file would be slow as we have to read a lot of data from the disk. We could build an index on each data file and store it in a separate index file. Each index file will be sorted on the record ID. If we want to search an ID in this index, the best we can do is a Binary Search. Would there be an even faster approach?</p><h3>Solution</h3><p>A Bloom filter is a <strong>probabilistic</strong> <strong>data structure</strong>, named after Burton Howard Bloom, who invented them in the 1970s. It is based on <strong>hashing </strong>designed to tell you, <strong>rapidly</strong> and <strong>memory-efficiently</strong>, <strong>whether an element is present in a set. </strong>Elements are not added to the set but their hash is.</p><p>The price paid for this efficiency is that a Bloom filter is a <strong>probabilistic data structure</strong>: it tells us whether the element is either <em><strong>definitely not</strong></em><strong> </strong>in the set or that it <em><strong>may be</strong></em><strong> </strong>in the set, thus <strong>false positives </strong>are possible.</p><h4><strong>How does it&nbsp;work?</strong></h4><ul><li><p>A Bloom filter is made of two elements: an array of <code>m</code> elements and a set of <code>k</code> hash functions. An empty Bloom filter is a bit-array of <code>m</code> bits, all set to 0 initially; and each hash function outputs an index between <code>0 </code>and <code>m-1</code>. There is no <code>1-1</code> correspondence between the elements of the array and the keys we add to the Bloom filter. We use <code>k</code> bits to store each entry for the Bloom filter.</p></li><li><p><code>k</code> is a constant that we pick when we create the data structure, so each and every entry we add is stored using the same amount of memory, <code>k</code> bits.</p></li><li><p>To add an element, feed it to the hash functions to get <code>k</code> bit positions, and set the bits at these positions to 1.</p></li><li><p>To test if an element is in the set, feed it to the hash functions to get <code>k</code> bit positions:<br>1. If any of the bits at these positions is 0, the element is <strong>definitely not</strong> in the set.<br>2. If all are 1, then the element <strong>may be</strong> in the set.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!L1fU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff837a4ba-ceb6-4fb8-9073-dc4508cea59a_1600x539.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!L1fU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff837a4ba-ceb6-4fb8-9073-dc4508cea59a_1600x539.jpeg 424w, https://substackcdn.com/image/fetch/$s_!L1fU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff837a4ba-ceb6-4fb8-9073-dc4508cea59a_1600x539.jpeg 848w, https://substackcdn.com/image/fetch/$s_!L1fU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff837a4ba-ceb6-4fb8-9073-dc4508cea59a_1600x539.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!L1fU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff837a4ba-ceb6-4fb8-9073-dc4508cea59a_1600x539.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!L1fU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff837a4ba-ceb6-4fb8-9073-dc4508cea59a_1600x539.jpeg" width="1456" height="490" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f837a4ba-ceb6-4fb8-9073-dc4508cea59a_1600x539.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:490,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&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_!L1fU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff837a4ba-ceb6-4fb8-9073-dc4508cea59a_1600x539.jpeg 424w, https://substackcdn.com/image/fetch/$s_!L1fU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff837a4ba-ceb6-4fb8-9073-dc4508cea59a_1600x539.jpeg 848w, https://substackcdn.com/image/fetch/$s_!L1fU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff837a4ba-ceb6-4fb8-9073-dc4508cea59a_1600x539.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!L1fU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff837a4ba-ceb6-4fb8-9073-dc4508cea59a_1600x539.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h4><strong>Choosing the Hash Functions</strong></h4><p>The hash functions used in a Bloom filter should be <strong><a href="http://en.wiktionary.org/wiki/independent_function">independent</a></strong> and <strong><a href="http://en.wikipedia.org/wiki/Uniform_distribution_%28discrete%29">uniformly distributed</a></strong>. Some examples of independent enough include <a href="https://sites.google.com/site/murmurhash/">murmur</a>, <a href="https://github.com/Cyan4973/xxHash">xxHash</a>, the <a href="http://isthe.com/chongo/tech/comp/fnv/">fnv</a> series of hashes, and <a href="https://web.archive.org/web/20061030103559/http://www.concentric.net/~Ttwang/tech/inthash.htm">HashMix</a>. The more hash functions you have, the slower your bloom filter, and the quicker it fills up. If you have too few, however, you may suffer too many false positives.</p><h4><strong>The false-positive ratio&nbsp;formula</strong></h4><p>The false positive rate of your filter can vary on the length of the filter. A larger filter will have less false positives, and a smaller one more. Considering that</p><blockquote><p><strong>n</strong> = number of elements you expect to insert,&nbsp;<br><strong>m</strong> = number of bits in the bloom filter and&nbsp;<br><strong>k</strong> = number of hash functions we use to map a key to k different positions in the array</p></blockquote><p>The rate of the false positives will be approximately</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CYFW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66add35d-ac98-4152-833a-9dfadc7bf702_194x128.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CYFW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66add35d-ac98-4152-833a-9dfadc7bf702_194x128.png 424w, https://substackcdn.com/image/fetch/$s_!CYFW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66add35d-ac98-4152-833a-9dfadc7bf702_194x128.png 848w, https://substackcdn.com/image/fetch/$s_!CYFW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66add35d-ac98-4152-833a-9dfadc7bf702_194x128.png 1272w, https://substackcdn.com/image/fetch/$s_!CYFW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66add35d-ac98-4152-833a-9dfadc7bf702_194x128.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CYFW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66add35d-ac98-4152-833a-9dfadc7bf702_194x128.png" width="194" height="128" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/66add35d-ac98-4152-833a-9dfadc7bf702_194x128.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:128,&quot;width&quot;:194,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&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_!CYFW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66add35d-ac98-4152-833a-9dfadc7bf702_194x128.png 424w, https://substackcdn.com/image/fetch/$s_!CYFW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66add35d-ac98-4152-833a-9dfadc7bf702_194x128.png 848w, https://substackcdn.com/image/fetch/$s_!CYFW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66add35d-ac98-4152-833a-9dfadc7bf702_194x128.png 1272w, https://substackcdn.com/image/fetch/$s_!CYFW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F66add35d-ac98-4152-833a-9dfadc7bf702_194x128.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Let&#8217;s see why. After a single bit has been stored in the bloom filter with a capacity of <em>m</em> bits, the probability that a specific bit is set to <em>1</em> is <em>1/m</em>. Then the probability that the same bit is set to <em>0 </em>after all the <em>k</em> bits used to store an element have been flipped is <em>(1&#8211;1/m)^k.</em></p><p>If we consider the events of flipping any specific bit to <em>1</em> as independent events, then after inserting <em>n </em>elements, for each individual bit the probability that the bit is still <em>0</em> is:&nbsp;</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3AZ0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51274bf8-9e08-48ef-8ad5-a9c2404f7997_426x162.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3AZ0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51274bf8-9e08-48ef-8ad5-a9c2404f7997_426x162.png 424w, https://substackcdn.com/image/fetch/$s_!3AZ0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51274bf8-9e08-48ef-8ad5-a9c2404f7997_426x162.png 848w, https://substackcdn.com/image/fetch/$s_!3AZ0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51274bf8-9e08-48ef-8ad5-a9c2404f7997_426x162.png 1272w, https://substackcdn.com/image/fetch/$s_!3AZ0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51274bf8-9e08-48ef-8ad5-a9c2404f7997_426x162.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3AZ0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51274bf8-9e08-48ef-8ad5-a9c2404f7997_426x162.png" width="426" height="162" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/51274bf8-9e08-48ef-8ad5-a9c2404f7997_426x162.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:162,&quot;width&quot;:426,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&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_!3AZ0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51274bf8-9e08-48ef-8ad5-a9c2404f7997_426x162.png 424w, https://substackcdn.com/image/fetch/$s_!3AZ0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51274bf8-9e08-48ef-8ad5-a9c2404f7997_426x162.png 848w, https://substackcdn.com/image/fetch/$s_!3AZ0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51274bf8-9e08-48ef-8ad5-a9c2404f7997_426x162.png 1272w, https://substackcdn.com/image/fetch/$s_!3AZ0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F51274bf8-9e08-48ef-8ad5-a9c2404f7997_426x162.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>To have a false positive, all the <em>k </em>bits corresponding to an element <em>V</em> must have been set to <em>1</em> independently, and the probability that all of those <em>k </em>bits are <em>1</em> is given by:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!EVP3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc30f96bb-bdee-4a37-8567-aa7f49ad973f_834x168.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!EVP3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc30f96bb-bdee-4a37-8567-aa7f49ad973f_834x168.png 424w, https://substackcdn.com/image/fetch/$s_!EVP3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc30f96bb-bdee-4a37-8567-aa7f49ad973f_834x168.png 848w, https://substackcdn.com/image/fetch/$s_!EVP3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc30f96bb-bdee-4a37-8567-aa7f49ad973f_834x168.png 1272w, https://substackcdn.com/image/fetch/$s_!EVP3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc30f96bb-bdee-4a37-8567-aa7f49ad973f_834x168.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!EVP3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc30f96bb-bdee-4a37-8567-aa7f49ad973f_834x168.png" width="834" height="168" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c30f96bb-bdee-4a37-8567-aa7f49ad973f_834x168.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:168,&quot;width&quot;:834,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&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_!EVP3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc30f96bb-bdee-4a37-8567-aa7f49ad973f_834x168.png 424w, https://substackcdn.com/image/fetch/$s_!EVP3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc30f96bb-bdee-4a37-8567-aa7f49ad973f_834x168.png 848w, https://substackcdn.com/image/fetch/$s_!EVP3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc30f96bb-bdee-4a37-8567-aa7f49ad973f_834x168.png 1272w, https://substackcdn.com/image/fetch/$s_!EVP3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc30f96bb-bdee-4a37-8567-aa7f49ad973f_834x168.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><h4>Choosing the size of the bloom&nbsp;filter</h4><p>To choose the size of a bloom filter, we:</p><ol><li><p>Choose an estimate value for <em>n</em></p></li><li><p>Choose a value for <em>m</em></p></li><li><p>Calculate the optimal value of <em>k</em></p></li><li><p>Calculate the error rate for the chosen values of <em>n</em>, <em>m</em>, and <em>k</em>. If it&#8217;s unacceptable, return to step 2 and change m; otherwise we&#8217;re done.</p></li></ol><p><a href="https://hur.st/about/">Thomas Hurst</a> has a <a href="https://hur.st/bloomfilter/">nice online page</a> that will help you choose an optimal size for your filter, or explore how the different parameters interact.</p><h4>Time and Space Complexity</h4><p>Let&#8217;s say we&#8217;re using a bloom filter with <em>m</em> bits and <em>k </em>hash functions, then insertion and search will both take <em>O(k)</em> time. We just need to run the input through all of the hash functions and then check the output bits.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!OMiT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72de7542-e041-4d1a-89ce-67cb610b8968_542x260.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!OMiT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72de7542-e041-4d1a-89ce-67cb610b8968_542x260.png 424w, https://substackcdn.com/image/fetch/$s_!OMiT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72de7542-e041-4d1a-89ce-67cb610b8968_542x260.png 848w, https://substackcdn.com/image/fetch/$s_!OMiT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72de7542-e041-4d1a-89ce-67cb610b8968_542x260.png 1272w, https://substackcdn.com/image/fetch/$s_!OMiT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72de7542-e041-4d1a-89ce-67cb610b8968_542x260.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!OMiT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72de7542-e041-4d1a-89ce-67cb610b8968_542x260.png" width="284" height="136.23616236162363" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/72de7542-e041-4d1a-89ce-67cb610b8968_542x260.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:260,&quot;width&quot;:542,&quot;resizeWidth&quot;:284,&quot;bytes&quot;:26711,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!OMiT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72de7542-e041-4d1a-89ce-67cb610b8968_542x260.png 424w, https://substackcdn.com/image/fetch/$s_!OMiT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72de7542-e041-4d1a-89ce-67cb610b8968_542x260.png 848w, https://substackcdn.com/image/fetch/$s_!OMiT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72de7542-e041-4d1a-89ce-67cb610b8968_542x260.png 1272w, https://substackcdn.com/image/fetch/$s_!OMiT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72de7542-e041-4d1a-89ce-67cb610b8968_542x260.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>If we make a bloom filter where <em>k=1 </em>then we just have a hash table that ignores collisions. The lower the false positive rate low, the larger the <em>m</em>. So, the space of the actual data structure is simply <em>O(m)</em>.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!e9W5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ea8297e-236a-4567-83c1-05424f8495c6_390x170.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!e9W5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ea8297e-236a-4567-83c1-05424f8495c6_390x170.png 424w, https://substackcdn.com/image/fetch/$s_!e9W5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ea8297e-236a-4567-83c1-05424f8495c6_390x170.png 848w, https://substackcdn.com/image/fetch/$s_!e9W5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ea8297e-236a-4567-83c1-05424f8495c6_390x170.png 1272w, https://substackcdn.com/image/fetch/$s_!e9W5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ea8297e-236a-4567-83c1-05424f8495c6_390x170.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!e9W5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ea8297e-236a-4567-83c1-05424f8495c6_390x170.png" width="250" height="108.97435897435898" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3ea8297e-236a-4567-83c1-05424f8495c6_390x170.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:170,&quot;width&quot;:390,&quot;resizeWidth&quot;:250,&quot;bytes&quot;:15419,&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;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!e9W5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ea8297e-236a-4567-83c1-05424f8495c6_390x170.png 424w, https://substackcdn.com/image/fetch/$s_!e9W5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ea8297e-236a-4567-83c1-05424f8495c6_390x170.png 848w, https://substackcdn.com/image/fetch/$s_!e9W5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ea8297e-236a-4567-83c1-05424f8495c6_390x170.png 1272w, https://substackcdn.com/image/fetch/$s_!e9W5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ea8297e-236a-4567-83c1-05424f8495c6_390x170.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><h4>Possible Implementation</h4><p>Let&#8217;s first define an interface for our implementation. Firstly, we&#8217;re going to need a method to add a key and one to check if the key exists. <em>PrintStats() </em>will print the number of total items we have added to the filter and the total number of bits sets. <em>SetHashFunction() </em>allows us to set a custom hash function and <em>Reset()</em> to clear the bloom filter.</p><pre><code>type Bloom interface {
 Add(key []byte) Bloom
 Check(key []byte) (bool, float64)
 PrintStats()
 SetHashFunction(hash.Hash)
 Reset()
}

func K(e float64) uint {
 return uint(math.Ceil(math.Log2(1 / e)))
}

func M(n uint, p, e float64) uint {
 // m =~ n / ((log(p)*log(1-p))/abs(log e))
 return uint(math.Ceil(float64(n) / ((math.Log(p) * math.Log(1-p)) / math.Abs(math.Log(e)))))
}</code></pre><p>And now let&#8217;s dive into the implementation. We&#8217;ll define a BloomFunction with the following attributes:</p><blockquote><p><strong>h</strong> = hash function<br><strong>m</strong> = number of bits in the bloom filter, will be divided into k partitions, or slices<br><strong>k</strong> = number of hash values we use to set and test bits<br><strong>s </strong>= the size of the partition, or slice; s = m / k<br><strong>p </strong>= the fill ratio of the filter partitions. It&#8217;s mainly used to calculate m at the start. p is not checked when new items are added. So if the fill ratio goes above p, the likelihood of false positives (error rate) will increase. By default, we use the fill ratio of p = 0.5<br><strong>e</strong> = the desired error rate of the bloom filter. The lower the e, the higher the k. By default, we use the error rate of e = 0.1% = 0.001.<br><strong>n</strong> = number of elements the filter is predicted to hold<br><strong>b</strong> = b is the set of bit array holding the bloom filters. There will be k b&#8217;s. We&#8217;re going to use the <a href="https://github.com/bits-and-blooms/bitset">golang&#8217;s bitset</a> package which is a mapping between non-negative integers and boolean values.<br><strong>c</strong> = number of items we have added to the filter<br><strong>bs</strong> = the list of bits</p></blockquote><pre><code>type BloomFunction struct {
 // h is the hash function
 h hash.Hash

 // the total number of bits for the bloom filter.
 m uint

 // the number of hash values used to set and test bits.
 k uint

 // the size of the partition, or slice.
 s uint

 // the fill ratio of the filter partitions. 
 p float64

 // the desired error rate of the bloom filter.
 e float64

 // number of elements the filter is predicted to hold
 n uint

 // b is the set of bit array holding the bloom filters.
 b *bitset.BitSet

 // number of items we have added to the filter
 c uint

 // the list of bits
 bs []uint
}

var _ Bloom = (*BloomFunction)(nil)

func NewBloomFilter(n uint) Bloom {
 var (
  p float64 = 0.5
  e float64 = 0.001
  k uint    = K(e)
  m uint    = M(n, p, e)
 )

 return &amp;BloomFunction{
  h:  fnv.New64(),
  n:  n,
  p:  p,
  e:  e,
  k:  k,
  m:  m,
  b:  bitset.New(m),
  bs: make([]uint, k),
 }
}</code></pre><p>When<strong> </strong>adding an item we simply pass it through the hash functions and store the results. To check if an item is in the set we iterate through the bitset and check whether every bit is set or not. If any of the bits are not, then it&#8217;s safe to assume the word doesn&#8217;t exist. If all bits are set then the item possibly exists with the probability of the formula we proved earlier.</p><pre><code>func (f *BloomFunction) SetHashFunction (h hash.Hash) {
 f.h = h
}

func (f *BloomFunction) Reset() {
 f.k = K(f.e)
 f.m = M(f.n, f.p, f.e)
 f.b = bitset.New(f.m)
 f.bs = make([]uint, f.k)

 if f.h == nil {
  f.h = fnv.New64()
 } else {
  f.h.Reset()
 }
}

func (f *BloomFunction) Add(item []byte) Bloom {
 f.bits(item)
 for _, v := range f.bs[:f.k] {
  f.b.Set(v)
 }
 f.c++
 return f
}

func (f *BloomFunction) Check(item []byte) (bool, float64) {
 f.bits(item)
 for _, v := range f.bs[:f.k] {
  if !f.b.Test(v) {
   return false, 0
  }
 }
 fPosProb := math.Pow(1.0-math.Pow(1.0-1.0/float64(f.m), float64(f.k*f.n)), float64(f.k))

 return true, fPosProb
}

func (f *BloomFunction) Count() uint {
 return f.c
}

func (f *BloomFunction) PrintStats() {
 fmt.Printf("m = %d, n = %d, k = %d, s = %d, p = %f, e = %f\n", f.m, f.n, f.k, f.s, f.p, f.e)
 fmt.Println("Total items:", f.c)
 c := f.b.Count()
 fmt.Printf("Total bits set: %d (%.1f%%)\n", c, float32(c)/float32(f.m)*100)
}

func (f *BloomFunction) bits(item []byte) {
 f.h.Reset()
 f.h.Write(item)
 s := f.h.Sum(nil)
 a := binary.BigEndian.Uint32(s[4:8])
 b := binary.BigEndian.Uint32(s[0:4])

 for i := range f.bs[:f.k] {
  f.bs[i] = (uint(a) + uint(b)*uint(i)) % f.m
 }
}</code></pre><p>Now let&#8217;s add 2 words to the filter &#8220;hello&#8221; and &#8220;world&#8221;. We can see that the &#8220;hello&#8221; word exists with a false positive probability of <em>0.001</em>.&nbsp;</p><pre><code>func main() {
 bf := NewBloomFilter(10)
 bf.Add([]byte("hello"))
 bf.Add([]byte("world"))
 check, prob := bf.Check([]byte("hello"))
 if check {
  fmt.Printf("Word exists with a false positive probability of %v\n", prob)
 } else {
  fmt.Printf("Word does not exists.")
 }
}
bf.PrintStats()

// Prints 

/*

Word exists with a false positive probability of 0.0010134325478480376

m = 144, n = 10, k = 10, s = 0, p = 0.500000, e = 0.001000
Total items: 2
Total bits set: 20 (13.9%)

*/</code></pre><p>Code available on <a href="https://github.com/yumed15/go-projects/tree/main/bloom-filter">github</a>.</p><h3>Applications</h3><p>In <strong>BigTable</strong> (and Cassandra), any read operation has to read from all SSTables that make up a Tablet. If these SSTables are not in memory, the read operation may end up doing many disk accesses. To reduce the number of disk accesses, BigTable uses Bloom filters. (<a href="https://cloud.google.com/blog/products/databases/cloud-bigtable-improves-single-row-read-throughput-by-up-to-50-percent">source</a>)</p><p>Bloom filters are created for SSTables (particularly for the locality groups). They help reduce the number of disk accesses by predicting if an SSTable may contain data corresponding to a particular row or column pair. For certain applications, a small amount of Tablet server memory used for storing Bloom filters drastically reduces the number of disk-seeks, thereby improving read performance.</p><p><strong>Medium</strong> uses Bloom filters in its Recommendation module to avoid showing the posts that the user has already seen.</p><h3>Resources:</h3><ul><li><p><a href="https://hur.st/bloomfilter/">Visualisation by Thomas Hurst showing how parameters influence each other</a></p></li><li><p><a href="https://llimllib.github.io/bloomfilter-tutorial/">Bloom Filters by Example</a></p></li></ul><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.diana-enache.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Diana&#8217;s Substack! 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>