<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Khushi Patel</title>
    <description>The latest articles on DEV Community by Khushi Patel (@khushindpatel).</description>
    <link>https://dev.to/khushindpatel</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1055368%2Fe0780331-7974-49ea-ba06-89417152f136.jpg</url>
      <title>DEV Community: Khushi Patel</title>
      <link>https://dev.to/khushindpatel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/khushindpatel"/>
    <language>en</language>
    <item>
      <title>Why Does LinkedIn Show "500+ Connections" Instead of the Exact Number?</title>
      <dc:creator>Khushi Patel</dc:creator>
      <pubDate>Mon, 29 Jun 2026 13:56:01 +0000</pubDate>
      <link>https://dev.to/khushindpatel/why-does-linkedin-show-500-connections-instead-of-the-exact-number-40a5</link>
      <guid>https://dev.to/khushindpatel/why-does-linkedin-show-500-connections-instead-of-the-exact-number-40a5</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Have you ever noticed that LinkedIn displays &lt;strong&gt;"500+ Connections"&lt;/strong&gt; once someone crosses 500 connections, instead of showing the exact count like 723 or 1,842?&lt;/p&gt;

&lt;p&gt;At first glance, this might seem like a simple UI choice, but it's actually a great example of a &lt;strong&gt;product and system design decision&lt;/strong&gt; where engineering, business goals, and user psychology come together.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Product Perspective
&lt;/h2&gt;

&lt;p&gt;LinkedIn's goal is not to help users compare who has more connections. Instead, it wants to indicate that someone has a strong professional network.&lt;/p&gt;

&lt;p&gt;From a networking perspective:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;450 Connections → Growing Network
500 Connections → Well Connected Professional
2500 Connections → Also Well Connected Professional
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For most users, knowing whether someone has 1,200 or 1,500 connections doesn't provide significant additional value.&lt;/p&gt;

&lt;p&gt;So LinkedIn chooses a threshold:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0 - 499  → Show exact number
500+     → Show "500+"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This communicates the important information while reducing unnecessary comparison.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Engineering Perspective
&lt;/h2&gt;

&lt;p&gt;Imagine LinkedIn has hundreds of millions of users.&lt;/p&gt;

&lt;p&gt;Every profile view needs to display:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name&lt;/li&gt;
&lt;li&gt;Headline&lt;/li&gt;
&lt;li&gt;Profile picture&lt;/li&gt;
&lt;li&gt;Connection count&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Showing an exact connection count requires keeping that number constantly updated whenever:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A connection request is accepted&lt;/li&gt;
&lt;li&gt;A connection is removed&lt;/li&gt;
&lt;li&gt;An account is deleted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For highly connected users, this count changes frequently.&lt;/p&gt;

&lt;p&gt;By displaying:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;500+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;523
524
525
526
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;LinkedIn reduces the importance of real-time precision.&lt;/p&gt;

&lt;p&gt;This gives engineers more flexibility around caching and data synchronization.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Distributed Systems Trade-off
&lt;/h2&gt;

&lt;p&gt;In system design, there's a concept called:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Precision vs Practical Value&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ask yourself:&lt;/p&gt;

&lt;p&gt;Would a user experience change if LinkedIn showed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;12,842
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;500+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Probably not.&lt;/p&gt;

&lt;p&gt;Since the exact value provides little additional business value, LinkedIn can optimize for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster profile loads&lt;/li&gt;
&lt;li&gt;Better caching&lt;/li&gt;
&lt;li&gt;Lower database reads&lt;/li&gt;
&lt;li&gt;Simpler distributed updates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a classic example of choosing an &lt;strong&gt;approximate answer when an exact answer isn't necessary&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-World System Design Principle
&lt;/h2&gt;

&lt;p&gt;A common mistake in software engineering is trying to make everything perfectly accurate.&lt;/p&gt;

&lt;p&gt;Good system designers ask:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Does the user actually need this precision?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instagram likes may update with slight delays&lt;/li&gt;
&lt;li&gt;YouTube subscriber counts are often rounded&lt;/li&gt;
&lt;li&gt;Social media follower counts are abbreviated&lt;/li&gt;
&lt;li&gt;LinkedIn shows 500+ connections&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These systems intentionally sacrifice precision because the business value of exactness is low.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Deliverable System Design Lesson
&lt;/h2&gt;

&lt;p&gt;One of the most important lessons in system design is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Build for the requirement, not for perfection.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the product requirement is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Show whether a user has a large professional network
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;500+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;solves the problem.&lt;/p&gt;

&lt;p&gt;If the requirement were:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Display the exact connection count for analytics purposes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then a different design would be necessary.&lt;/p&gt;

&lt;p&gt;Great engineering decisions are often about identifying where precision matters and where it doesn't.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;LinkedIn shows &lt;strong&gt;500+ connections&lt;/strong&gt; because the exact number provides little additional value to users after a certain threshold. This decision reduces social comparison, simplifies the user experience, and gives engineers more flexibility in scaling, caching, and synchronizing connection counts.&lt;/p&gt;

&lt;p&gt;It's a great example of a system design principle: &lt;strong&gt;optimize for what users actually need, not for perfect accuracy everywhere.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How Does Google Docs Handle Two People Editing the Same Line at the Exact Same Time?</title>
      <dc:creator>Khushi Patel</dc:creator>
      <pubDate>Thu, 25 Jun 2026 14:23:04 +0000</pubDate>
      <link>https://dev.to/khushindpatel/how-does-google-docs-handle-two-people-editing-the-same-line-at-the-exact-same-time-38gi</link>
      <guid>https://dev.to/khushindpatel/how-does-google-docs-handle-two-people-editing-the-same-line-at-the-exact-same-time-38gi</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;One of the most impressive features of Google Docs is real-time collaboration. Multiple users can edit the same document simultaneously and see changes appear almost instantly.&lt;/p&gt;

&lt;p&gt;But what happens when two users edit the &lt;strong&gt;exact same line&lt;/strong&gt; at the &lt;strong&gt;exact same moment&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;How does Google Docs prevent one user's changes from overwriting another's? Is there a lock on the document? Does someone lose their changes?&lt;/p&gt;

&lt;p&gt;The answer lies in a distributed systems technique called &lt;strong&gt;Operational Transformation (OT)&lt;/strong&gt;, combined with real-time synchronization architecture.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Imagine a document containing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello World
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now consider two users:&lt;/p&gt;

&lt;h3&gt;
  
  
  User A
&lt;/h3&gt;

&lt;p&gt;Adds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello Beautiful World
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  User B
&lt;/h3&gt;

&lt;p&gt;At the same time adds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello Amazing World
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both users started editing from the same document version.&lt;/p&gt;

&lt;p&gt;The challenge is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Both changes are valid&lt;/li&gt;
&lt;li&gt;Both arrive at the server simultaneously&lt;/li&gt;
&lt;li&gt;Neither should overwrite the other&lt;/li&gt;
&lt;li&gt;Everyone should eventually see the same document&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why Traditional Database Updates Fail
&lt;/h2&gt;

&lt;p&gt;A typical CRUD system works like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Read Data
Modify Data
Update Data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If two users update simultaneously:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User A -&amp;gt; Save
User B -&amp;gt; Save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second save overwrites the first.&lt;/p&gt;

&lt;p&gt;This is known as a:&lt;/p&gt;

&lt;h3&gt;
  
  
  Lost Update Problem
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Final Result:
Hello Amazing World
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;User A's changes disappear.&lt;/p&gt;

&lt;p&gt;For collaborative editors, this is unacceptable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Google's Solution: Operational Transformation (OT)
&lt;/h2&gt;

&lt;p&gt;Instead of sending the entire document after every edit, Google Docs sends:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Operations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Insert "Beautiful" at position 6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Insert "Amazing" at position 6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server receives operations rather than complete document snapshots.&lt;/p&gt;




&lt;h2&gt;
  
  
  Understanding Operations
&lt;/h2&gt;

&lt;p&gt;Original text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello World
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  User A Operation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Insert "Beautiful " at position 6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  User B Operation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Insert "Amazing " at position 6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both operations target the same location.&lt;/p&gt;

&lt;p&gt;Without conflict resolution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello Beautiful World
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello Amazing World
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One edit wins.&lt;/p&gt;

&lt;p&gt;Google Docs does something smarter.&lt;/p&gt;




&lt;h2&gt;
  
  
  Operational Transformation in Action
&lt;/h2&gt;

&lt;p&gt;Server receives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Operation A:
Insert "Beautiful " at position 6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then receives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Operation B:
Insert "Amazing " at position 6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second operation is transformed based on the first.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Insert at position 6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;it becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Insert at position 16
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;because the document has already grown.&lt;/p&gt;

&lt;p&gt;Final result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello Beautiful Amazing World
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both users' edits survive.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-Time Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          User A
             |
             |
             v
      WebSocket Server
             ^
             |
             |
          User B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Google Docs maintains a persistent connection using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WebSockets&lt;/li&gt;
&lt;li&gt;Real-time event streams&lt;/li&gt;
&lt;li&gt;Version tracking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every edit is sent as a tiny operation rather than a full document.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step-by-Step Flow
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1
&lt;/h3&gt;

&lt;p&gt;Both users load:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Version 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 2
&lt;/h3&gt;

&lt;p&gt;User A sends:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Insert "Beautiful"
Version 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 3
&lt;/h3&gt;

&lt;p&gt;User B sends:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Insert "Amazing"
Version 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 4
&lt;/h3&gt;

&lt;p&gt;Server processes User A first.&lt;/p&gt;

&lt;p&gt;Document becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Version 101
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 5
&lt;/h3&gt;

&lt;p&gt;Server notices User B is based on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Version 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;while current document is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Version 101
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now OT transforms User B's operation before applying it.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 6
&lt;/h3&gt;

&lt;p&gt;Document updates successfully.&lt;/p&gt;

&lt;p&gt;Everyone eventually sees:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello Beautiful Amazing World
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What About Cursor Positions?
&lt;/h2&gt;

&lt;p&gt;Imagine you're typing while another person inserts text before your cursor.&lt;/p&gt;

&lt;p&gt;Without adjustment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cursor jumps randomly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Google Docs tracks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cursor position&lt;/li&gt;
&lt;li&gt;Selection ranges&lt;/li&gt;
&lt;li&gt;User presence&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When operations are transformed, cursor positions are transformed too.&lt;/p&gt;

&lt;p&gt;This is why your typing experience remains smooth even when dozens of users are editing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Does Google Lock the Document?
&lt;/h2&gt;

&lt;p&gt;No.&lt;/p&gt;

&lt;p&gt;Document locking would be terrible for collaboration.&lt;/p&gt;

&lt;p&gt;Imagine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User A is editing line 20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everyone else would have to wait.&lt;/p&gt;

&lt;p&gt;Instead, Google allows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Concurrent editing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and resolves conflicts intelligently.&lt;/p&gt;

&lt;p&gt;This provides a much better user experience.&lt;/p&gt;




&lt;h2&gt;
  
  
  Modern Alternative: CRDTs
&lt;/h2&gt;

&lt;p&gt;Many newer collaborative systems use:&lt;/p&gt;

&lt;h3&gt;
  
  
  Conflict-free Replicated Data Types (CRDT)
&lt;/h3&gt;

&lt;p&gt;Used by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Figma&lt;/li&gt;
&lt;li&gt;Notion (parts of architecture)&lt;/li&gt;
&lt;li&gt;Modern collaborative editors&lt;/li&gt;
&lt;li&gt;Offline-first applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CRDTs allow clients to merge changes without requiring a central transformation server.&lt;/p&gt;

&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Better offline support&lt;/li&gt;
&lt;li&gt;Easier synchronization&lt;/li&gt;
&lt;li&gt;High scalability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Google Docs was originally built using Operational Transformation, although modern collaborative systems increasingly adopt CRDT-based approaches.&lt;/p&gt;




&lt;h2&gt;
  
  
  System Design Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    +----------------+
                    | Document Store |
                    +----------------+
                            ^
                            |
                            |
+--------+         +----------------+         +--------+
| User A | &amp;lt;-----&amp;gt; | Sync Server    | &amp;lt;-----&amp;gt; | User B |
+--------+         +----------------+         +--------+
                            |
                            |
                    Operational
                   Transformation
                            |
                            v
                    Document State
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Sync Server is responsible for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Receiving operations&lt;/li&gt;
&lt;li&gt;Version tracking&lt;/li&gt;
&lt;li&gt;Conflict resolution&lt;/li&gt;
&lt;li&gt;Operation transformation&lt;/li&gt;
&lt;li&gt;Broadcasting updates&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Interview Perspective
&lt;/h2&gt;

&lt;p&gt;A common System Design interview question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Design Google Docs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Expected discussion points:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;WebSockets for real-time communication&lt;/li&gt;
&lt;li&gt;Operational Transformation or CRDT&lt;/li&gt;
&lt;li&gt;Version numbers&lt;/li&gt;
&lt;li&gt;Conflict resolution&lt;/li&gt;
&lt;li&gt;Document persistence&lt;/li&gt;
&lt;li&gt;Cursor synchronization&lt;/li&gt;
&lt;li&gt;Horizontal scaling of collaboration servers&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Mentioning OT and CRDT immediately demonstrates a strong understanding of collaborative systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Google Docs does not lock documents during editing.&lt;/li&gt;
&lt;li&gt;Users send operations instead of entire document snapshots.&lt;/li&gt;
&lt;li&gt;Operational Transformation resolves simultaneous edits.&lt;/li&gt;
&lt;li&gt;The server transforms conflicting operations so both changes can survive.&lt;/li&gt;
&lt;li&gt;WebSockets provide low-latency synchronization.&lt;/li&gt;
&lt;li&gt;Cursor positions are transformed along with document changes.&lt;/li&gt;
&lt;li&gt;Modern systems often use CRDTs as an alternative approach.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The magic behind Google Docs is not preventing conflicts—it's intelligently transforming and merging edits so that every user eventually sees the same consistent document.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Why Doesn't an E-Commerce Payment API Get Called Twice When Users Double-Click the Pay Button?</title>
      <dc:creator>Khushi Patel</dc:creator>
      <pubDate>Mon, 22 Jun 2026 13:34:15 +0000</pubDate>
      <link>https://dev.to/khushindpatel/why-doesnt-an-e-commerce-payment-api-get-called-twice-when-users-double-click-the-pay-button-4mh4</link>
      <guid>https://dev.to/khushindpatel/why-doesnt-an-e-commerce-payment-api-get-called-twice-when-users-double-click-the-pay-button-4mh4</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Imagine you're purchasing a product online. You click the &lt;strong&gt;"Pay Now"&lt;/strong&gt; button, and due to a slow internet connection or impatience, you accidentally click it again.&lt;/p&gt;

&lt;p&gt;A common question among developers is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If two requests are sent, why doesn't the payment get processed twice?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The answer lies in a combination of &lt;strong&gt;frontend protection, backend safeguards, database design, and payment gateway architecture&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this blog, we'll explore how modern e-commerce systems prevent duplicate payments and the system design principles behind it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Consider the following sequence:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User clicks "Pay Now"&lt;/li&gt;
&lt;li&gt;Browser sends payment request&lt;/li&gt;
&lt;li&gt;User clicks again before the first request completes&lt;/li&gt;
&lt;li&gt;Browser sends another payment request&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Without proper handling:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Customer may be charged twice&lt;/li&gt;
&lt;li&gt;Two orders may be created&lt;/li&gt;
&lt;li&gt;Inventory may be deducted twice&lt;/li&gt;
&lt;li&gt;Refund processes become necessary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a critical financial issue that every payment system must prevent.&lt;/p&gt;




&lt;h2&gt;
  
  
  First Layer: Frontend Protection
&lt;/h2&gt;

&lt;p&gt;The simplest protection happens in the UI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Disable the Payment Button
&lt;/h3&gt;

&lt;p&gt;After the first click:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handlePayment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;makePayment&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;disabled=&lt;/span&gt;&lt;span class="s"&gt;{loading}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Pay Now
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What Happens?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;User clicks once&lt;/li&gt;
&lt;li&gt;Button becomes disabled&lt;/li&gt;
&lt;li&gt;Additional clicks are ignored&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why This Isn't Enough
&lt;/h3&gt;

&lt;p&gt;Frontend validation can be bypassed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Browser refresh&lt;/li&gt;
&lt;li&gt;Multiple tabs&lt;/li&gt;
&lt;li&gt;Network retries&lt;/li&gt;
&lt;li&gt;Malicious requests&lt;/li&gt;
&lt;li&gt;Mobile app bugs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, the backend must still assume duplicate requests can arrive.&lt;/p&gt;




&lt;h2&gt;
  
  
  Second Layer: Idempotency Keys
&lt;/h2&gt;

&lt;p&gt;This is the most important concept in payment systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Is Idempotency?
&lt;/h3&gt;

&lt;p&gt;An operation is idempotent if performing it multiple times produces the same result.&lt;/p&gt;

&lt;p&gt;For payments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Pay ₹100 once
Pay ₹100 again
Pay ₹100 again
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Only one actual payment is processed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Generating an Idempotency Key
&lt;/h2&gt;

&lt;p&gt;When a payment request is initiated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;payment_id = "PAY_123456"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"paymentId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PAY_123456"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The backend stores this key.&lt;/p&gt;

&lt;h3&gt;
  
  
  First Request
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PAY_123456
Status: Processing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Payment starts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Second Request
&lt;/h3&gt;

&lt;p&gt;Backend receives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PAY_123456
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;System checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;payments&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;payment_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'PAY_123456'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Record already exists.&lt;/p&gt;

&lt;p&gt;Instead of processing again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Return existing response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No second payment occurs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture Flow
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
  |
  v
Frontend
  |
  v
API Gateway
  |
  v
Payment Service
  |
  +---- Check Idempotency Key
  |
  +---- Already Exists?
          |
       YES --&amp;gt; Return Previous Result
          |
       NO
          |
          v
Process Payment
          |
          v
Store Result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pattern is used by almost every modern payment platform.&lt;/p&gt;




&lt;h2&gt;
  
  
  Database-Level Protection
&lt;/h2&gt;

&lt;p&gt;Even if two requests reach the server simultaneously, the database provides another safety layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unique Constraint
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;payments&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;payment_id&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="nb"&gt;DECIMAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Suppose two servers receive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PAY_123456
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;at exactly the same moment.&lt;/p&gt;

&lt;p&gt;The first insert succeeds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;payments&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second insert fails:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Duplicate Key Exception
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thus, duplicate records cannot exist.&lt;/p&gt;




&lt;h2&gt;
  
  
  Handling Race Conditions
&lt;/h2&gt;

&lt;p&gt;Consider a distributed environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request A --&amp;gt; Server 1
Request B --&amp;gt; Server 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both arrive within milliseconds.&lt;/p&gt;

&lt;p&gt;Without coordination:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Server 1 -&amp;gt; Process Payment
Server 2 -&amp;gt; Process Payment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Duplicate charge risk.&lt;/p&gt;




&lt;h2&gt;
  
  
  Distributed Locking
&lt;/h2&gt;

&lt;p&gt;Many systems use Redis locks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flow
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Acquire Lock
      |
      v
Process Payment
      |
      v
Release Lock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LOCK:PAY_123456
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Server 1:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Lock Acquired
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Server 2:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Lock Exists
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Server 2 waits or returns existing result.&lt;/p&gt;




&lt;h2&gt;
  
  
  Payment Gateway Protection
&lt;/h2&gt;

&lt;p&gt;Payment providers also implement idempotency.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stripe&lt;/li&gt;
&lt;li&gt;Razorpay&lt;/li&gt;
&lt;li&gt;PayPal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When sending a request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /payments
Idempotency-Key: PAY_123456
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Gateway stores:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PAY_123456
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If another request arrives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Same key detected
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Gateway returns the original response instead of charging again.&lt;/p&gt;

&lt;p&gt;This creates protection even if your application has a bug.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-World Payment Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                User
                  |
                  v
         +----------------+
         |  Frontend App  |
         +----------------+
                  |
                  v
         +----------------+
         | API Gateway    |
         +----------------+
                  |
                  v
         +----------------+
         | Payment Service|
         +----------------+
                  |
      +-----------+------------+
      |                        |
      v                        v
 Redis Lock            Payment Database
      |                        |
      +-----------+------------+
                  |
                  v
          Payment Gateway
                  |
                  v
              Bank
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every layer contributes to preventing duplicate transactions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Multiple Protection Layers Are Needed
&lt;/h2&gt;

&lt;p&gt;A common misconception is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Disabling the button solves the problem."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In reality:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Frontend Disable&lt;/td&gt;
&lt;td&gt;Prevent accidental clicks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API Idempotency&lt;/td&gt;
&lt;td&gt;Prevent duplicate processing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database Unique Key&lt;/td&gt;
&lt;td&gt;Prevent duplicate records&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Redis Lock&lt;/td&gt;
&lt;td&gt;Prevent race conditions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Payment Gateway Idempotency&lt;/td&gt;
&lt;td&gt;Prevent duplicate charges&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Payment systems rely on &lt;strong&gt;defense in depth&lt;/strong&gt;, not a single safeguard.&lt;/p&gt;




&lt;h2&gt;
  
  
  Interview Perspective
&lt;/h2&gt;

&lt;p&gt;A common System Design interview question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How would you prevent duplicate payment processing?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Expected answer:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Disable button on frontend&lt;/li&gt;
&lt;li&gt;Generate unique payment/order ID&lt;/li&gt;
&lt;li&gt;Use idempotency keys&lt;/li&gt;
&lt;li&gt;Store payment status in database&lt;/li&gt;
&lt;li&gt;Add unique constraints&lt;/li&gt;
&lt;li&gt;Use distributed locking for concurrent requests&lt;/li&gt;
&lt;li&gt;Leverage payment gateway idempotency support&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Discussing all layers demonstrates strong backend and distributed systems knowledge.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Double-clicking a payment button can generate multiple requests.&lt;/li&gt;
&lt;li&gt;Frontend protection alone is insufficient.&lt;/li&gt;
&lt;li&gt;Idempotency keys are the primary mechanism for preventing duplicate payments.&lt;/li&gt;
&lt;li&gt;Databases enforce uniqueness through constraints.&lt;/li&gt;
&lt;li&gt;Redis locks handle concurrent requests across multiple servers.&lt;/li&gt;
&lt;li&gt;Payment gateways provide an additional safety layer.&lt;/li&gt;
&lt;li&gt;Modern payment systems use multiple layers of protection to guarantee that a customer is charged only once.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A successful payment architecture is not about stopping duplicate requests it is about ensuring duplicate requests produce only one financial transaction.&lt;/p&gt;

</description>
      <category>system</category>
      <category>design</category>
      <category>ui</category>
      <category>react</category>
    </item>
    <item>
      <title>If Everything Is Running on Localhost, Why Do We Still Get CORS Errors?</title>
      <dc:creator>Khushi Patel</dc:creator>
      <pubDate>Fri, 19 Jun 2026 13:36:32 +0000</pubDate>
      <link>https://dev.to/khushindpatel/if-everything-is-running-on-localhost-why-do-we-still-get-cors-errors-58k5</link>
      <guid>https://dev.to/khushindpatel/if-everything-is-running-on-localhost-why-do-we-still-get-cors-errors-58k5</guid>
      <description>&lt;p&gt;One question almost every frontend developer asks at some point:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"My frontend is running on localhost:3000 and my backend is running on localhost:5000. Both are on my own machine. Why am I still getting a CORS error?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It feels strange because both applications are literally running on the same laptop.&lt;/p&gt;

&lt;p&gt;The answer lies in how browsers define an &lt;strong&gt;Origin&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is an Origin?
&lt;/h2&gt;

&lt;p&gt;An origin is made up of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Protocol + Domain + Port
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:5000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Same protocol ✅&lt;/li&gt;
&lt;li&gt;Same domain ✅&lt;/li&gt;
&lt;li&gt;Different ports ❌&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because the ports are different, the browser treats them as two different origins.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Happens During a Request?
&lt;/h2&gt;

&lt;p&gt;Imagine your React app is running on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and it calls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5000/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the browser's perspective:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Origin A → localhost:3000
Origin B → localhost:5000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is considered a cross-origin request.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Does the Browser Care?
&lt;/h2&gt;

&lt;p&gt;Imagine if websites could freely call APIs from any origin.&lt;/p&gt;

&lt;p&gt;A malicious website could:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read your banking data&lt;/li&gt;
&lt;li&gt;Access your private APIs&lt;/li&gt;
&lt;li&gt;Perform actions on your behalf&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To prevent this, browsers enforce the &lt;strong&gt;Same-Origin Policy&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;By default:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Website A cannot access Website B's resources
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;unless Website B explicitly allows it.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Does CORS Solve This?
&lt;/h2&gt;

&lt;p&gt;CORS stands for:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cross-Origin Resource Sharing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It is simply a mechanism that lets the server tell the browser:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Yes, I trust requests coming from this origin."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Example response header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Access-Control-Allow-Origin: http://localhost:3000
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the browser allows the frontend to access the response.&lt;/p&gt;




&lt;h2&gt;
  
  
  Important Thing To Understand
&lt;/h2&gt;

&lt;p&gt;The backend usually receives the request successfully.&lt;/p&gt;

&lt;p&gt;The CORS error is often raised by the browser after receiving the response.&lt;/p&gt;

&lt;p&gt;The flow looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Frontend
    ↓
Backend Receives Request ✅
    ↓
Backend Sends Response ✅
    ↓
Browser Blocks Response ❌
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's why you sometimes see the API hit in your backend logs but still get a CORS error in the browser.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Doesn't Postman Show CORS Errors?
&lt;/h2&gt;

&lt;p&gt;Because CORS is a browser security feature.&lt;/p&gt;

&lt;p&gt;Tools like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Postman&lt;/li&gt;
&lt;li&gt;cURL&lt;/li&gt;
&lt;li&gt;Insomnia&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;don't enforce browser security policies.&lt;/p&gt;

&lt;p&gt;So the same request works perfectly there.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Key Takeaway
&lt;/h2&gt;

&lt;p&gt;Even though both applications are running on the same machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;localhost:3000
localhost:5000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;they are considered different origins because the ports are different.&lt;/p&gt;

&lt;p&gt;The browser doesn't care that they're on the same laptop. It only cares about the origin.&lt;/p&gt;

&lt;p&gt;That's why CORS exists, and that's why adding the correct &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt; header fixes the issue.&lt;/p&gt;

</description>
      <category>api</category>
      <category>beginners</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>System Design: How Does a UPI Payment Reach the Chai Wala in Just Seconds?</title>
      <dc:creator>Khushi Patel</dc:creator>
      <pubDate>Wed, 17 Jun 2026 14:15:46 +0000</pubDate>
      <link>https://dev.to/khushindpatel/system-design-how-does-a-upi-payment-reach-the-chai-wala-in-just-seconds-nk6</link>
      <guid>https://dev.to/khushindpatel/system-design-how-does-a-upi-payment-reach-the-chai-wala-in-just-seconds-nk6</guid>
      <description>&lt;p&gt;Imagine this.&lt;/p&gt;

&lt;p&gt;You buy a ₹20 chai from your local chai wala.&lt;/p&gt;

&lt;p&gt;You open &lt;strong&gt;Paytm&lt;/strong&gt;, scan his QR code, and make the payment.&lt;/p&gt;

&lt;p&gt;But here's the interesting part:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your Paytm is linked to &lt;strong&gt;HDFC Bank&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The chai wala's Paytm is linked to &lt;strong&gt;SBI&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The money moves between two completely different banks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And yet...&lt;/p&gt;

&lt;p&gt;Within 2-3 seconds both of you receive a notification.&lt;/p&gt;

&lt;p&gt;How does this happen so fast?&lt;/p&gt;

&lt;p&gt;Let's follow the journey of that ₹20.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: You Scan the QR Code
&lt;/h2&gt;

&lt;p&gt;The QR code doesn't contain money.&lt;/p&gt;

&lt;p&gt;It usually contains information like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UPI ID: chaiwala@sbi
Merchant Details
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you enter ₹20 and click Pay, Paytm creates a payment request.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Paytm Doesn't Transfer Money
&lt;/h2&gt;

&lt;p&gt;Many people think Paytm sends the money.&lt;/p&gt;

&lt;p&gt;It doesn't.&lt;/p&gt;

&lt;p&gt;Paytm is simply acting as an interface.&lt;/p&gt;

&lt;p&gt;The actual money movement happens between banks through UPI.&lt;/p&gt;

&lt;p&gt;So the flow looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You
 ↓
Paytm
 ↓
UPI Network
 ↓
Banks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 3: Request Goes To NPCI
&lt;/h2&gt;

&lt;p&gt;The payment request is sent to the UPI infrastructure operated by the National Payments Corporation of India.&lt;/p&gt;

&lt;p&gt;Think of NPCI as the traffic controller of India's UPI system.&lt;/p&gt;

&lt;p&gt;It knows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which bank owns your account&lt;/li&gt;
&lt;li&gt;Which bank owns the chai wala's account&lt;/li&gt;
&lt;li&gt;Where the request should be routed&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 4: Your Bank Verifies Everything
&lt;/h2&gt;

&lt;p&gt;NPCI forwards the request to your bank.&lt;/p&gt;

&lt;p&gt;Your bank checks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the account active?&lt;/li&gt;
&lt;li&gt;Is there enough balance?&lt;/li&gt;
&lt;li&gt;Is the UPI PIN correct?&lt;/li&gt;
&lt;li&gt;Is the transaction suspicious?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If everything is valid, the bank approves the debit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Account Balance = ₹1000
Payment = ₹20

Approved ✅
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 5: Chai Wala's Bank Gets The Credit Request
&lt;/h2&gt;

&lt;p&gt;Now NPCI forwards the request to the chai wala's bank.&lt;/p&gt;

&lt;p&gt;His bank verifies the account and credits ₹20.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Chai Wala Balance
₹500
   ↓
₹520
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 6: Success Message Everywhere
&lt;/h2&gt;

&lt;p&gt;Once both banks confirm:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NPCI marks transaction successful&lt;/li&gt;
&lt;li&gt;Paytm receives success response&lt;/li&gt;
&lt;li&gt;Chai wala's Paytm receives success response&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Within seconds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You: Payment Successful ✅

Chai Wala: ₹20 Received ✅
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  But Wait... Did The Money Actually Move?
&lt;/h2&gt;

&lt;p&gt;This is where things get interesting.&lt;/p&gt;

&lt;p&gt;Millions of UPI transactions happen every minute.&lt;/p&gt;

&lt;p&gt;Banks don't physically transfer money one-by-one for every chai, samosa, or grocery purchase.&lt;/p&gt;

&lt;p&gt;Instead, they maintain settlement records.&lt;/p&gt;

&lt;p&gt;Throughout the day:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HDFC owes SBI
SBI owes ICICI
ICICI owes Axis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NPCI keeps track of these obligations.&lt;/p&gt;

&lt;p&gt;Later, settlement happens through the banking system in bulk.&lt;/p&gt;

&lt;p&gt;This is much faster than moving actual money for every transaction individually.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Is It So Fast?
&lt;/h2&gt;

&lt;p&gt;Several engineering decisions make this possible:&lt;/p&gt;

&lt;h3&gt;
  
  
  Parallel Processing
&lt;/h3&gt;

&lt;p&gt;Banks verify requests simultaneously.&lt;/p&gt;

&lt;h3&gt;
  
  
  High-Speed Network
&lt;/h3&gt;

&lt;p&gt;NPCI operates highly optimized payment infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lightweight Messages
&lt;/h3&gt;

&lt;p&gt;Only transaction information is exchanged, not huge amounts of data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deferred Settlement
&lt;/h3&gt;

&lt;p&gt;Banks settle balances later rather than moving money instantly every time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Simplified Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You
 │
 ▼
Paytm App
 │
 ▼
NPCI UPI Switch
 │
 ├─────────────► Your Bank
 │                    │
 │                    ▼
 │              Debit Money
 │
 ▼
Chai Wala Bank
 │
 ▼
Credit Money
 │
 ▼
Success Response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All of this happens in just a few seconds.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;When you pay ₹20 to a chai wala:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Paytm is only the interface.&lt;/li&gt;
&lt;li&gt;NPCI acts as the traffic controller.&lt;/li&gt;
&lt;li&gt;Your bank debits the amount.&lt;/li&gt;
&lt;li&gt;The merchant's bank credits the amount.&lt;/li&gt;
&lt;li&gt;Settlement between banks happens later.&lt;/li&gt;
&lt;li&gt;Optimized infrastructure allows the entire process to complete in seconds.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next time you hear that familiar "Payment Received" sound from the chai wala's phone, remember:&lt;/p&gt;

&lt;p&gt;Behind that simple beep, multiple systems, banks, servers, and networks coordinated in real time to move money across the country.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>System Design: How Do We Host an App That Runs a Job Every 5 Minutes?</title>
      <dc:creator>Khushi Patel</dc:creator>
      <pubDate>Fri, 12 Jun 2026 12:21:49 +0000</pubDate>
      <link>https://dev.to/khushindpatel/system-design-how-do-we-host-an-app-that-runs-a-job-every-5-minutes-1i50</link>
      <guid>https://dev.to/khushindpatel/system-design-how-do-we-host-an-app-that-runs-a-job-every-5-minutes-1i50</guid>
      <description>&lt;p&gt;Imagine you're building an app that needs to perform a task every 5 minutes.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send reminder notifications&lt;/li&gt;
&lt;li&gt;Check product expiry dates&lt;/li&gt;
&lt;li&gt;Generate daily reports&lt;/li&gt;
&lt;li&gt;Sync data from third-party APIs&lt;/li&gt;
&lt;li&gt;Clean old records from the database&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A common beginner question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If nobody opens my app, who will trigger these jobs every 5 minutes?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's break down how this works in production.&lt;/p&gt;




&lt;h2&gt;
  
  
  Option 1: Cron Job on a Server
&lt;/h2&gt;

&lt;p&gt;The simplest solution is using a Cron Job.&lt;/p&gt;

&lt;p&gt;A cron job is a scheduler built into Linux that can execute commands at specific intervals.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;*&lt;/span&gt;/5 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; node reminderJob.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Every 5 minutes
Run reminderJob.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────┐
│ Linux Server│
└──────┬──────┘
       │
       ▼
  Cron Scheduler
       │
       ▼
   Node.js Job
       │
       ▼
    Database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Works well for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Small projects&lt;/li&gt;
&lt;li&gt;Internal tools&lt;/li&gt;
&lt;li&gt;MVPs&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Problem With a Single Server
&lt;/h2&gt;

&lt;p&gt;What happens if the server crashes?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Server Down
     ↓
Cron Stops
     ↓
Jobs Missed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For critical applications, this is unacceptable.&lt;/p&gt;

&lt;p&gt;Imagine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Payment settlement jobs&lt;/li&gt;
&lt;li&gt;Order processing&lt;/li&gt;
&lt;li&gt;OTP cleanup&lt;/li&gt;
&lt;li&gt;Subscription renewals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Missing even one execution can create problems.&lt;/p&gt;




&lt;h2&gt;
  
  
  Option 2: Dedicated Background Worker
&lt;/h2&gt;

&lt;p&gt;Large systems separate API servers and background workers.&lt;/p&gt;

&lt;p&gt;Architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        Users
          │
          ▼
    API Servers
          │
          ▼
      Database

          ▲
          │

    Worker Service
          │
          ▼
    Scheduled Jobs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;APIs remain fast&lt;/li&gt;
&lt;li&gt;Jobs don't affect user requests&lt;/li&gt;
&lt;li&gt;Easier to scale independently&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Option 3: Kubernetes CronJobs
&lt;/h2&gt;

&lt;p&gt;Modern cloud applications often run on Kubernetes.&lt;/p&gt;

&lt;p&gt;Kubernetes provides a resource called CronJob.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*/5&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every 5 minutes Kubernetes automatically creates a container and runs the job.&lt;/p&gt;

&lt;p&gt;Architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      Kubernetes
           │
           ▼
      CronJob
           │
           ▼
    New Container
           │
           ▼
       Execute Job
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatic retries&lt;/li&gt;
&lt;li&gt;Auto-healing&lt;/li&gt;
&lt;li&gt;Easy deployment&lt;/li&gt;
&lt;li&gt;Cloud-native&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Preventing Duplicate Execution
&lt;/h2&gt;

&lt;p&gt;Suppose you have 3 servers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Server A
Server B
Server C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If all three execute the same job:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Send Notification
Send Notification
Send Notification
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Users receive the same notification three times.&lt;/p&gt;

&lt;p&gt;Not good.&lt;/p&gt;




&lt;h2&gt;
  
  
  Distributed Locking
&lt;/h2&gt;

&lt;p&gt;To ensure only one server executes the job, companies use distributed locks.&lt;/p&gt;

&lt;p&gt;Popular choices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Redis Lock&lt;/li&gt;
&lt;li&gt;Database Lock&lt;/li&gt;
&lt;li&gt;ZooKeeper&lt;/li&gt;
&lt;li&gt;etcd&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Worker Starts
      │
      ▼
Acquire Lock
      │
      ▼
Lock Success ?
   /       \
 Yes        No
  │          │
  ▼          ▼
Run Job    Exit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only one worker gets the lock.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Big Companies Do It
&lt;/h2&gt;

&lt;p&gt;Companies rarely depend on a single cron job.&lt;/p&gt;

&lt;p&gt;Typical architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                Scheduler
                    │
                    ▼
              Message Queue
                    │
        ┌───────────┼───────────┐
        ▼           ▼           ▼
     Worker 1    Worker 2    Worker 3
        │           │           │
        └───────────┼───────────┘
                    ▼
                 Database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Popular technologies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cron&lt;/li&gt;
&lt;li&gt;Kubernetes CronJobs&lt;/li&gt;
&lt;li&gt;Redis&lt;/li&gt;
&lt;li&gt;RabbitMQ&lt;/li&gt;
&lt;li&gt;Apache Kafka&lt;/li&gt;
&lt;li&gt;AWS EventBridge&lt;/li&gt;
&lt;li&gt;Google Cloud Scheduler&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The scheduler creates tasks.&lt;/p&gt;

&lt;p&gt;Workers process those tasks.&lt;/p&gt;

&lt;p&gt;This makes the system scalable and fault tolerant.&lt;/p&gt;




&lt;h2&gt;
  
  
  Example: Expiry Reminder App
&lt;/h2&gt;

&lt;p&gt;Let's say you built an app that stores expiry dates.&lt;/p&gt;

&lt;p&gt;Every 5 minutes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Scheduler triggers a job.&lt;/li&gt;
&lt;li&gt;Job finds products expiring soon.&lt;/li&gt;
&lt;li&gt;Notification tasks are added to a queue.&lt;/li&gt;
&lt;li&gt;Workers send notifications.&lt;/li&gt;
&lt;li&gt;Results are stored in the database.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cron Scheduler
      │
      ▼
Expiry Checker
      │
      ▼
Database Query
      │
      ▼
Message Queue
      │
      ▼
Notification Workers
      │
      ▼
Firebase / APNs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;A scheduled task running every 5 minutes is usually not handled by user traffic.&lt;/p&gt;

&lt;p&gt;Production systems use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cron Jobs&lt;/li&gt;
&lt;li&gt;Background Workers&lt;/li&gt;
&lt;li&gt;Kubernetes CronJobs&lt;/li&gt;
&lt;li&gt;Message Queues&lt;/li&gt;
&lt;li&gt;Distributed Locks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The bigger the scale, the more important reliability, retries, and duplicate prevention become.&lt;/p&gt;

&lt;p&gt;Next time you receive a notification exactly on time, remember:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Somewhere in the cloud, a scheduler woke up, executed a job, and triggered that notification.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>cloud</category>
      <category>programming</category>
      <category>devops</category>
      <category>automation</category>
    </item>
    <item>
      <title>How Does Netflix Remember Exactly Where You Stopped Watching?</title>
      <dc:creator>Khushi Patel</dc:creator>
      <pubDate>Wed, 10 Jun 2026 14:02:07 +0000</pubDate>
      <link>https://dev.to/khushindpatel/how-does-netflix-remember-exactly-where-you-stopped-watching-5df7</link>
      <guid>https://dev.to/khushindpatel/how-does-netflix-remember-exactly-where-you-stopped-watching-5df7</guid>
      <description>&lt;p&gt;Imagine this:&lt;/p&gt;

&lt;p&gt;You're watching a show on your TV. Halfway through an episode, you turn the TV off and leave. A few minutes later, you open Netflix on your phone, and somehow it starts playing from the &lt;strong&gt;exact same second&lt;/strong&gt; where you stopped.&lt;/p&gt;

&lt;p&gt;No loading. No searching. No manually finding your spot.&lt;/p&gt;

&lt;p&gt;How does Netflix make this happen almost instantly for millions of users?&lt;/p&gt;




&lt;h2&gt;
  
  
  The Secret: Continuous Progress Syncing
&lt;/h2&gt;

&lt;p&gt;While you're watching a movie or series, Netflix doesn't wait until you finish the episode to save your progress.&lt;/p&gt;

&lt;p&gt;Every few seconds, the app sends small updates to Netflix's servers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User ID&lt;/li&gt;
&lt;li&gt;Show ID&lt;/li&gt;
&lt;li&gt;Episode ID&lt;/li&gt;
&lt;li&gt;Current playback position (e.g., 18 minutes 42 seconds)&lt;/li&gt;
&lt;li&gt;Timestamp&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A simplified record might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"userId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12345&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"showId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;789&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"episodeId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"position"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1122&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;1122&lt;/code&gt; represents the number of seconds watched.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Happens When You Close the App?
&lt;/h2&gt;

&lt;p&gt;Suppose you stop watching at &lt;strong&gt;18:42&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Before the TV app closes, Netflix sends one final update containing your latest position.&lt;/p&gt;

&lt;p&gt;This information is stored in a highly distributed database that can be accessed from anywhere in the world.&lt;/p&gt;

&lt;p&gt;Now Netflix knows exactly where you left off.&lt;/p&gt;




&lt;h2&gt;
  
  
  Opening Netflix on Another Device
&lt;/h2&gt;

&lt;p&gt;A few minutes later, you open Netflix on your phone.&lt;/p&gt;

&lt;p&gt;The app immediately asks Netflix:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Where did this user stop watching?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Netflix returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"episodeId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"position"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"18:42"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The phone then starts streaming from that exact point.&lt;/p&gt;

&lt;p&gt;To the user, it feels like magic.&lt;/p&gt;

&lt;p&gt;Behind the scenes, it's simply fast synchronization between devices and servers.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Challenge: Scale
&lt;/h2&gt;

&lt;p&gt;Doing this for one user is easy.&lt;/p&gt;

&lt;p&gt;Netflix has hundreds of millions of users watching content simultaneously on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TVs&lt;/li&gt;
&lt;li&gt;Mobile phones&lt;/li&gt;
&lt;li&gt;Tablets&lt;/li&gt;
&lt;li&gt;Laptops&lt;/li&gt;
&lt;li&gt;Gaming consoles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means Netflix processes billions of progress updates every day.&lt;/p&gt;

&lt;p&gt;Their systems must handle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Massive write traffic&lt;/li&gt;
&lt;li&gt;Low-latency reads&lt;/li&gt;
&lt;li&gt;Global availability&lt;/li&gt;
&lt;li&gt;Device synchronization&lt;/li&gt;
&lt;li&gt;Failure recovery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All while keeping playback smooth.&lt;/p&gt;




&lt;h2&gt;
  
  
  What If Two Devices Are Watching at the Same Time?
&lt;/h2&gt;

&lt;p&gt;Suppose you're watching on your TV and phone simultaneously.&lt;/p&gt;

&lt;p&gt;Which position should Netflix save?&lt;/p&gt;

&lt;p&gt;Netflix usually stores timestamps along with progress updates.&lt;/p&gt;

&lt;p&gt;The latest valid update wins.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TV Update:
Position: 10:15
Time: 10:00:01

Phone Update:
Position: 12:30
Time: 10:00:05
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since the phone's update arrived later, Netflix treats that as the newest progress.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why It Feels Instant
&lt;/h2&gt;

&lt;p&gt;Netflix uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Distributed databases&lt;/li&gt;
&lt;li&gt;Global data centers&lt;/li&gt;
&lt;li&gt;Intelligent caching&lt;/li&gt;
&lt;li&gt;Event-driven systems&lt;/li&gt;
&lt;li&gt;Real-time synchronization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a result, when you switch devices, your watch history is already available and ready to use.&lt;/p&gt;




&lt;h2&gt;
  
  
  System Design Flow
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TV App
   │
   │ Progress Update (18:42)
   ▼
Netflix API
   │
   ▼
Distributed Database
   │
   ▼
Mobile App Requests Progress
   │
   ▼
Returns 18:42
   │
   ▼
Playback Resumes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Next Time You Switch Devices...
&lt;/h2&gt;

&lt;p&gt;Remember that Netflix isn't magically tracking your progress.&lt;/p&gt;

&lt;p&gt;It's continuously saving tiny updates while you watch and making them available across the world within seconds.&lt;/p&gt;

&lt;p&gt;A simple feature for users.&lt;/p&gt;

&lt;p&gt;An enormous distributed systems challenge for engineers.&lt;/p&gt;




&lt;h3&gt;
  
  
  Question for You
&lt;/h3&gt;

&lt;p&gt;If Netflix can sync your watch progress worldwide in seconds, how do you think live-streaming platforms handle &lt;strong&gt;2–5 crore viewers&lt;/strong&gt; watching the same event simultaneously?&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>coding</category>
      <category>webdev</category>
      <category>ai</category>
    </item>
    <item>
      <title>Implement LFU using LRU</title>
      <dc:creator>Khushi Patel</dc:creator>
      <pubDate>Thu, 02 Apr 2026 09:27:06 +0000</pubDate>
      <link>https://dev.to/khushindpatel/implement-lfu-using-lru-8fl</link>
      <guid>https://dev.to/khushindpatel/implement-lfu-using-lru-8fl</guid>
      <description>&lt;h3&gt;
  
  
  📌 Core Idea
&lt;/h3&gt;

&lt;p&gt;LFU (Least Frequently Used) means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remove the &lt;strong&gt;least frequently used&lt;/strong&gt; key&lt;/li&gt;
&lt;li&gt;If multiple keys have same frequency → remove &lt;strong&gt;least recently used (LRU)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  📦 Data Structures Used
&lt;/h3&gt;

&lt;p&gt;We maintain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;key → node&lt;/code&gt; (for O(1) access)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;freq → doubly linked list&lt;/code&gt; (group nodes by frequency)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;minFreq&lt;/code&gt; (track minimum frequency in cache)&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🧱 Structure Visualization
&lt;/h3&gt;

&lt;p&gt;Freq = 1 → [ most recent .... least recent ]&lt;br&gt;&lt;br&gt;
Freq = 2 → [ most recent .... least recent ]&lt;br&gt;&lt;br&gt;
Freq = 3 → [ most recent .... least recent ]  &lt;/p&gt;

&lt;p&gt;Each frequency has its &lt;strong&gt;own LRU list&lt;/strong&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  🚀 Example Walkthrough
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Capacity = 2
&lt;/h4&gt;


&lt;h4&gt;
  
  
  Step 1: put(1,10)
&lt;/h4&gt;

&lt;p&gt;Freq 1: [1]&lt;br&gt;&lt;br&gt;
minFreq = 1  &lt;/p&gt;


&lt;h4&gt;
  
  
  Step 2: put(2,20)
&lt;/h4&gt;

&lt;p&gt;Freq 1: &lt;a href="https://dev.to2%20is%20most%20recent"&gt;2, 1&lt;/a&gt;&lt;br&gt;&lt;br&gt;
minFreq = 1  &lt;/p&gt;


&lt;h4&gt;
  
  
  Step 3: get(1)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Access key &lt;code&gt;1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Increase its frequency: 1 → 2&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Freq 1: [2]&lt;br&gt;&lt;br&gt;
Freq 2: [1]&lt;br&gt;&lt;br&gt;
minFreq = 1  &lt;/p&gt;

&lt;p&gt;👉 We removed &lt;code&gt;1&lt;/code&gt; from freq 1 and added to freq 2&lt;/p&gt;


&lt;h4&gt;
  
  
  Step 4: put(3,30)
&lt;/h4&gt;

&lt;p&gt;Cache is FULL → eviction needed  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;minFreq = 1
&lt;/li&gt;
&lt;li&gt;Look at Freq 1 → [2]
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 Remove &lt;code&gt;2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After insertion:&lt;/p&gt;

&lt;p&gt;Freq 1: [3]&lt;br&gt;&lt;br&gt;
Freq 2: [1]&lt;br&gt;&lt;br&gt;
minFreq = 1  &lt;/p&gt;


&lt;h4&gt;
  
  
  Step 5: get(3)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Move &lt;code&gt;3&lt;/code&gt; from freq 1 → freq 2&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Freq 1: []&lt;br&gt;&lt;br&gt;
Freq 2: [3, 1]&lt;br&gt;&lt;br&gt;
minFreq = 2   (freq 1 is empty now)  &lt;/p&gt;


&lt;h4&gt;
  
  
  Step 6: put(4,40)
&lt;/h4&gt;

&lt;p&gt;Cache full → eviction  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;minFreq = 2
&lt;/li&gt;
&lt;li&gt;Freq 2 → [3, 1]
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 Remove LRU → &lt;code&gt;1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After insertion:&lt;/p&gt;

&lt;p&gt;Freq 1: [4]&lt;br&gt;&lt;br&gt;
Freq 2: [3]&lt;br&gt;&lt;br&gt;
minFreq = 1  &lt;/p&gt;


&lt;h3&gt;
  
  
  🔥 Key Observations
&lt;/h3&gt;
&lt;h4&gt;
  
  
  1. Why multiple lists?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Different frequencies → cannot maintain in single list
&lt;/li&gt;
&lt;li&gt;Each frequency maintains its own LRU order
&lt;/li&gt;
&lt;/ul&gt;


&lt;h4&gt;
  
  
  2. Why minFreq?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Helps directly find which list to evict from in O(1)
&lt;/li&gt;
&lt;/ul&gt;


&lt;h4&gt;
  
  
  3. Why doubly linked list?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;O(1) removal
&lt;/li&gt;
&lt;li&gt;Maintain LRU order inside same frequency
&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  🧠 Mental Model
&lt;/h3&gt;

&lt;p&gt;Think of LFU like books:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shelf 1 → least used books
&lt;/li&gt;
&lt;li&gt;Shelf 2 → moderately used
&lt;/li&gt;
&lt;li&gt;Shelf 3 → most used
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When removing:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pick least used shelf
&lt;/li&gt;
&lt;li&gt;Remove oldest book from that shelf
&lt;/li&gt;
&lt;/ol&gt;


&lt;h3&gt;
  
  
  🧩 Mapping to Code
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concept&lt;/th&gt;
&lt;th&gt;Code&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Increase frequency&lt;/td&gt;
&lt;td&gt;updateFreq(node)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Remove LRU&lt;/td&gt;
&lt;td&gt;list-&amp;gt;tail-&amp;gt;prev&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Track minimum&lt;/td&gt;
&lt;td&gt;minFreq&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Insert new node&lt;/td&gt;
&lt;td&gt;freq = 1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h3&gt;
  
  
  🚨 Common Mistake
&lt;/h3&gt;

&lt;p&gt;When a frequency list becomes empty:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;freq&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;minFreq&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;minFreq&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;❗ If you don’t update minFreq, eviction will break&lt;/p&gt;

&lt;h3&gt;
  
  
  Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LFUCache&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;public:&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;freq&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;freq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;public:&lt;/span&gt;
        &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;tail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;addFront&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;removeNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;prevv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;nextt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;prevv&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nextt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;nextt&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prevv&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;cap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;minFreq&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;unordered_map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;keyNode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;        &lt;span class="c1"&gt;// key -&amp;gt; node&lt;/span&gt;
    &lt;span class="n"&gt;unordered_map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;freqList&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;       &lt;span class="c1"&gt;// freq -&amp;gt; DLL&lt;/span&gt;

    &lt;span class="n"&gt;LFUCache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;capacity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;cap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;capacity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;minFreq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;updateFreq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;freq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;freq&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;freqList&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;freq&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;removeNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;freq&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;minFreq&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;freqList&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;freq&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;minFreq&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;freq&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;freqList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;freq&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;freqList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;freqList&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;freq&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;freqList&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;freq&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;addFront&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keyNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;keyNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;keyNode&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="n"&gt;updateFreq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cap&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keyNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;keyNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;keyNode&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
            &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;updateFreq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keyNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;cap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;freqList&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;minFreq&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
            &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;nodeToRemove&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="n"&gt;keyNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;erase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nodeToRemove&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;removeNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nodeToRemove&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;newNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;minFreq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;freqList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;freqList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;freqList&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;freqList&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;addFront&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newNode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;keyNode&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newNode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>datastructures</category>
      <category>dsa</category>
      <category>programming</category>
    </item>
    <item>
      <title>7-Day Beginner’s Mindmap to Learn GenAI</title>
      <dc:creator>Khushi Patel</dc:creator>
      <pubDate>Tue, 15 Jul 2025 04:26:23 +0000</pubDate>
      <link>https://dev.to/khushindpatel/7-day-beginners-mindmap-to-learn-genai-4flb</link>
      <guid>https://dev.to/khushindpatel/7-day-beginners-mindmap-to-learn-genai-4flb</guid>
      <description>&lt;p&gt;Perfect for anyone curious about ChatGPT, LLMs, image generation &amp;amp; more!&lt;br&gt;
Each day has clear topics + free resources (courses, videos, articles) 🧠✨&lt;/p&gt;

&lt;p&gt;👉 Explore the full mindmap here: &lt;a href="https://miro.com/app/board/uXjVJeJ7gJk=/?share_link_id=128758728459" rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Follow on Instagram &lt;a href="https://www.instagram.com/codeandcrunch/" rel="noopener noreferrer"&gt;CodeAndCrunch&lt;/a&gt;&lt;/p&gt;

</description>
      <category>chatgpt</category>
      <category>llm</category>
      <category>ai</category>
      <category>learning</category>
    </item>
    <item>
      <title>Understanding Video Streaming and Optimize Media Downloads 📽️📂</title>
      <dc:creator>Khushi Patel</dc:creator>
      <pubDate>Tue, 04 Mar 2025 12:48:33 +0000</pubDate>
      <link>https://dev.to/khushindpatel/understanding-video-streaming-and-optimize-media-downloads-k6i</link>
      <guid>https://dev.to/khushindpatel/understanding-video-streaming-and-optimize-media-downloads-k6i</guid>
      <description>&lt;p&gt;Video streaming has become an integral part of our digital experience, powering everything from YouTube and Netflix to social media platforms like Facebook, Twitter (X), and Instagram. While streaming is optimized for seamless playback, there are times when users might want to download content for offline access. This raises the question: How does video streaming work, and how can we optimize media downloads while staying within ethical boundaries?&lt;/p&gt;

&lt;p&gt;In this post, we’ll break down the core principles of video streaming, explore how video downloads work, and discuss ways to optimize media retrieval efficiently. &lt;/p&gt;

&lt;h2&gt;
  
  
  How Video Streaming Works ⚒️
&lt;/h2&gt;

&lt;p&gt;Streaming works by delivering media data in small chunks rather than requiring users to download the entire file before playback. Here’s a breakdown of key concepts:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Streaming Protocols
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;HTTP Live Streaming (HLS)&lt;/strong&gt;: Used by Apple devices and many streaming platforms, HLS splits videos into small &lt;code&gt;.ts&lt;/code&gt;segments, which are loaded dynamically.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dynamic Adaptive Streaming over HTTP (DASH):&lt;/strong&gt; A widely used protocol that adjusts video quality based on network conditions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Real-Time Messaging Protocol (RTMP):&lt;/strong&gt; Previously popular for live streaming but now largely replaced by HLS/DASH.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Video Encoding &amp;amp; Compression
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Codecs (H.264, H.265, VP9, AV1):&lt;/strong&gt; Used to compress video files while maintaining quality.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bitrate Adaptation&lt;/strong&gt;: Streaming platforms adjust video quality based on bandwidth to avoid buffering.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Content Delivery Networks (CDNs)
&lt;/h3&gt;

&lt;p&gt;CDNs store video files across multiple servers worldwide to reduce latency and improve load times.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Media Downloads Work
&lt;/h2&gt;

&lt;p&gt;Downloading a video is different from streaming because it involves retrieving the full file instead of fetching segments dynamically. However, many platforms restrict direct downloads to protect content rights. Here’s how media downloads typically work:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Direct File Download
&lt;/h3&gt;

&lt;p&gt;Some platforms provide direct download options (e.g., YouTube Premium for offline viewing).&lt;/p&gt;

&lt;h3&gt;
  
  
  2. M3U8 Parsing (HLS Streams)
&lt;/h3&gt;

&lt;p&gt;Some media files are segmented into .m3u8 playlists containing multiple &lt;code&gt;.ts&lt;/code&gt; files. These need to be reconstructed into a full video. &lt;a href="https://www.fastpix.io/blog/a-complete-guide-to-m3u8-files-in-hls-streaming" rel="noopener noreferrer"&gt;read more&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. API-Based Downloads
&lt;/h3&gt;

&lt;p&gt;Some services provide APIs to fetch media content legally, All in One Downloader &lt;a href="https://www.allinonedownloader.co/" rel="noopener noreferrer"&gt;All in One Downloader&lt;/a&gt; is a great example of this which allow user to download video from multiple social media platform&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By leveraging the right technologies and understanding video formats, you can enhance your workflow and make media retrieval more seamless. &lt;/p&gt;

&lt;p&gt;What are your thoughts on video downloads and streaming optimization? Have you built any tools to enhance media retrieval? Let’s discuss in the comments! 🚀&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>news</category>
      <category>opensource</category>
    </item>
    <item>
      <title>you know about this tools?</title>
      <dc:creator>Khushi Patel</dc:creator>
      <pubDate>Thu, 30 Jan 2025 12:56:42 +0000</pubDate>
      <link>https://dev.to/khushindpatel/-5he</link>
      <guid>https://dev.to/khushindpatel/-5he</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/khushindpatel" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1055368%2Fe0780331-7974-49ea-ba06-89417152f136.jpg" alt="khushindpatel"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/khushindpatel/5-open-source-tools-every-saas-founder-should-use-for-free-1joi" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;5 Open Source Tools Every SaaS Founder Should Use for Free 🚀&lt;/h2&gt;
      &lt;h3&gt;Khushi Patel ・ Jan 30&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#startup&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#marketing&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#saas&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>startup</category>
      <category>marketing</category>
      <category>saas</category>
      <category>javascript</category>
    </item>
    <item>
      <title>5 Open Source Tools Every SaaS Founder Should Use for Free 🚀</title>
      <dc:creator>Khushi Patel</dc:creator>
      <pubDate>Thu, 30 Jan 2025 12:52:44 +0000</pubDate>
      <link>https://dev.to/khushindpatel/5-open-source-tools-every-saas-founder-should-use-for-free-1joi</link>
      <guid>https://dev.to/khushindpatel/5-open-source-tools-every-saas-founder-should-use-for-free-1joi</guid>
      <description>&lt;p&gt;Starting a SaaS business is exciting—until you realize how expensive it can get. Hosting, analytics, support, marketing... it all adds up!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjs026cp5emaysm6o7600.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjs026cp5emaysm6o7600.gif" alt="Image description" width="300" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But what if I told you there are powerful open-source tools that can save you thousands of dollars while giving you full control over your data?&lt;/p&gt;

&lt;p&gt;Yep, you heard that right! Here are five open-source gems every SaaS founder should be using (for free!) to build, grow, and scale their startup.&lt;/p&gt;

&lt;p&gt;1️⃣ Plausible – Privacy-Friendly Analytics 📊&lt;br&gt;
Why pay for Google Analytics when you can own your data? Plausible is an open-source, lightweight analytics tool that gives you clear insights without slowing down your website. Plus, it’s GDPR compliant by design—no cookies, no tracking nightmares.&lt;/p&gt;

&lt;p&gt;🔹 Why you'll love it?&lt;br&gt;
✔️ Simple, clean UI (No need for a data science degree!)&lt;br&gt;
✔️ No invasive tracking—privacy-first 🌍&lt;br&gt;
✔️ Self-host it for zero monthly costs&lt;/p&gt;

&lt;p&gt;💡 Perfect for: Founders who care about privacy and want an easy-to-understand analytics dashboard.&lt;/p&gt;

&lt;p&gt;👉 Check it out: &lt;a href="//plausible.io"&gt;plausible.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2️⃣ Chatwoot – Open-Source Live Chat &amp;amp; Support 💬&lt;br&gt;
Forget Intercom’s hefty price tag! Chatwoot is an open-source alternative that helps you chat with customers in real-time, manage support tickets, and automate conversations.&lt;/p&gt;

&lt;p&gt;🔹 Why you'll love it?&lt;br&gt;
✔️ Omnichannel support (Website, WhatsApp, Facebook, etc.)&lt;br&gt;
✔️ Customizable &amp;amp; developer-friendly&lt;br&gt;
✔️ No per-agent pricing, scale for free!&lt;/p&gt;

&lt;p&gt;💡 Perfect for: SaaS founders who want direct customer engagement without burning a hole in their wallet.&lt;/p&gt;

&lt;p&gt;👉 Check it out: &lt;a href="//chatwoot.com"&gt;chatwoot.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3️⃣ PostHog – Product Analytics on Steroids 🔥&lt;br&gt;
Want to know how users interact with your SaaS? PostHog gives you session replays, feature flags, and event tracking all in one place. It’s like Mixpanel &amp;amp; Hotjar had an open-source baby.&lt;/p&gt;

&lt;p&gt;🔹 Why you'll love it?&lt;br&gt;
✔️ Event-based analytics (track anything!)&lt;br&gt;
✔️ User session recordings for UI/UX insights&lt;br&gt;
✔️ Feature flags to test new features safely&lt;/p&gt;

&lt;p&gt;💡 Perfect for: SaaS founders who want deep product insights to optimize their UX.&lt;/p&gt;

&lt;p&gt;👉 Check it out: &lt;a href="//posthog.com"&gt;posthog.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4️⃣ NocoDB – Open-Source Airtable Alternative 🏗️&lt;br&gt;
Who needs Airtable when NocoDB lets you turn any database into a smart, spreadsheet like interface? You can build admin panels, internal tools, and dashboards—no coding required!&lt;/p&gt;

&lt;p&gt;🔹 Why you'll love it?&lt;br&gt;
✔️ Works with MySQL, PostgreSQL, and more&lt;br&gt;
✔️ Drag &amp;amp; drop interface, just like Airtable&lt;br&gt;
✔️ Self-host it = No monthly fees!&lt;/p&gt;

&lt;p&gt;💡 Perfect for: SaaS founders who need a database-driven app without expensive SaaS subscriptions.&lt;/p&gt;

&lt;p&gt;👉 Check it out: &lt;a href="//nocodb.com"&gt;nocodb.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5️⃣ Mautic – Open-Source Marketing Automation 🎯&lt;br&gt;
Want to automate email campaigns, lead scoring, and customer journeys without paying for HubSpot or ActiveCampaign? Mautic is your answer!&lt;/p&gt;

&lt;p&gt;🔹 Why you'll love it?&lt;br&gt;
✔️ Powerful marketing automation (emails, SMS, social, web)&lt;br&gt;
✔️ Advanced segmentation &amp;amp; lead scoring&lt;br&gt;
✔️ Self-hosted = Own your data + Save $$$&lt;/p&gt;

&lt;p&gt;💡 Perfect for: SaaS founders who need automated marketing on a budget.&lt;/p&gt;

&lt;p&gt;👉 Check it out: &lt;a href="//mautic.org"&gt;mautic.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Final Thoughts 💡&lt;br&gt;
SaaS founders, stop burning cash on expensive tools when open-source alternatives are just as powerful! These tools let you:&lt;br&gt;
✅ Cut costs 💰&lt;br&gt;
✅ Own your data 🔐&lt;br&gt;
✅ Customize and scale your startup your way 🚀&lt;/p&gt;

&lt;p&gt;Which open-source tool are you most excited to try? Drop a comment below! 👇&lt;/p&gt;

</description>
      <category>startup</category>
      <category>marketing</category>
      <category>saas</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
