<?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: Deepak Singh Solanki</title>
    <description>The latest articles on DEV Community by Deepak Singh Solanki (@deepakinsights).</description>
    <link>https://dev.to/deepakinsights</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3857390%2F146eedf6-36a4-4d16-ad60-bf9445feaea3.png</url>
      <title>DEV Community: Deepak Singh Solanki</title>
      <link>https://dev.to/deepakinsights</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/deepakinsights"/>
    <language>en</language>
    <item>
      <title>Stateful vs Stateless: How a Perfect System Failed</title>
      <dc:creator>Deepak Singh Solanki</dc:creator>
      <pubDate>Sat, 11 Apr 2026 04:31:03 +0000</pubDate>
      <link>https://dev.to/deepakinsights/stateful-vs-stateless-how-a-perfect-system-failed-10af</link>
      <guid>https://dev.to/deepakinsights/stateful-vs-stateless-how-a-perfect-system-failed-10af</guid>
      <description>&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%2F4c0ita1j2zxl2anb0ynh.png" 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%2F4c0ita1j2zxl2anb0ynh.png" width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In 2020, COVID had changed everything. Schools and colleges were shutdown and education moved online. Classes, attendance, assignments, exams, fees — everything was online.&lt;/p&gt;

&lt;p&gt;Our client had built their ERP years before COVID. It was working fine. They had onboard many schools and institutions. But COVID pushed the usage to a different level. Teachers who were used to teaching in classrooms were now taking online classes. Students who were used to sitting in classrooms were now attending from home. Using the ERP was no longer a choice, it was mandatory.&lt;/p&gt;

&lt;p&gt;The system started breaking.&lt;/p&gt;

&lt;p&gt;Everyone was getting logged out randomly. Teachers lost work in middle of sessions. Students could not access homework or online classes. Even the staff was struggling with their daily work.&lt;/p&gt;

&lt;p&gt;Client’s tech team started working on it. They checked everything. Load balancer config, server health, database. Everything looked correct.&lt;/p&gt;

&lt;p&gt;They could not find the problem.&lt;/p&gt;

&lt;p&gt;That is when they called us. For expert advice.&lt;/p&gt;

&lt;p&gt;I remember looking at their architecture for the first time. Three servers and Nginx load balancer on top. A perfect setup. I also agreed with their team. The design was correct. Nothing was obviously wrong.&lt;/p&gt;

&lt;p&gt;Everything was correct and still the system was failing.&lt;/p&gt;

&lt;p&gt;That is the day I came to know something I will never forget.&lt;/p&gt;

&lt;p&gt;Most developers never think about small configurations, but that can silently break the system completely.&lt;/p&gt;

&lt;p&gt;That configuration was about the session and that story is what I want to share with you today.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Investigation
&lt;/h3&gt;

&lt;p&gt;When we got access to their system, we started from scratch. No assumptions.&lt;/p&gt;

&lt;p&gt;We checked with the Nginx load balancer configuration first. Round robin was set up correctly. All three servers were getting equal traffic. We did not find any issue there.&lt;/p&gt;

&lt;p&gt;Then we checked the servers. CPU, memory, logs. Everything was healthy. There were no crashes, no errors and no unusual spikes.&lt;/p&gt;

&lt;p&gt;Then we checked the database. Queries were fine. No slow queries and no connection issues.&lt;/p&gt;

&lt;p&gt;We spent almost a week and were clueless. Load balancer, servers, database, deployment config. Nothing was wrong. The system was built correctly.&lt;/p&gt;

&lt;p&gt;Then we moved to the code.&lt;/p&gt;

&lt;p&gt;We started checking the authentication and most complained endpoints one by one. Login, dashboard, fee management, homework. Suddenly, something clicked in my mind.&lt;/p&gt;

&lt;p&gt;Sessions.&lt;/p&gt;

&lt;p&gt;The application was using Laravel session-based authentication. I checked and found that sessions were not stored in the database or Redis. They were stored locally on each server.&lt;/p&gt;

&lt;p&gt;That was it. That was the problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Root Cause
&lt;/h3&gt;

&lt;p&gt;Now, Let’s discuss about what was actually happening.&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%2Fstcwk5u4jksfl0mh5j7c.png" 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%2Fstcwk5u4jksfl0mh5j7c.png" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When a user logs in to a Laravel application, the server creates a session. That session stores the user’s identity. Who they are, what they can access. By default, Laravel stores this session in files on the same server.&lt;/p&gt;

&lt;p&gt;They setup three servers behind a load balancer.&lt;/p&gt;

&lt;p&gt;User visits the website. Request goes to Server A. Server A authenticates the user and creates a session. Session is stored locally on Server A. User is logged in.&lt;/p&gt;

&lt;p&gt;Next request from the same user. Load balancer sends it to Server B. Server B has no session for this user. It does not know who this person is. So it throws them out.&lt;/p&gt;

&lt;p&gt;That is it. That is why everyone was getting logged out randomly. It was not because of any bug in the code and not because of any misconfiguration in the load balancer. The load balancer was doing exactly what it was supposed to do. Distributing traffic across all three servers.&lt;/p&gt;

&lt;p&gt;The problem was that each server was living in its own world. Servers had no shared memory and no shared session. Three servers working as three separate brains.&lt;/p&gt;

&lt;p&gt;This is what we call a stateful system.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Analogy
&lt;/h3&gt;

&lt;p&gt;Let me explain this with something we all have experienced.&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%2Frl8izymfyvt6ankw6o2x.png" 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%2Frl8izymfyvt6ankw6o2x.png" width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Think about a guard standing at school gate. He knows students by face and remembers everyone. When a student arrives, he allows entry without checking id card. No id card required. The guard remembers.&lt;/p&gt;

&lt;p&gt;Now that guard retires.&lt;/p&gt;

&lt;p&gt;New guard joins next day. He does not know anyone. Rahul comes to school. New guard stops him. Rahul says he is a student here. But new guard has no memory of Rahul. No record. Nothing. So Rahul is not allowed inside even though he is a valid student.&lt;/p&gt;

&lt;p&gt;This is exactly what was happening in their system. Server A was the old guard, it remembered the user. But load balancer sent next request to Server B, server B was the new guard. He had no memory and user gets kicked out.&lt;/p&gt;

&lt;p&gt;This is a stateful system. The server remembers you. But that memory is private. All other servers will treat you as stranger.&lt;/p&gt;

&lt;p&gt;Now think about a different school that have fingerprint machines at every gate. Gate 1, Gate 2, Gate 3. It does not matter which gate you use. Machine scans your fingerprint and verifies it instantly. Machine does not need to remember you. Your fingerprint works the proof.&lt;/p&gt;

&lt;p&gt;This is a stateless system. The server does not remember you. But every request have enough information to verify you. No memory needed. Any server can handle your request.&lt;/p&gt;

&lt;p&gt;That is the difference.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a Stateful System?
&lt;/h3&gt;

&lt;p&gt;A stateful system remembers the client. Every time a request comes in, the server uses the previous information to handle it.&lt;/p&gt;

&lt;p&gt;Session based authentication is the most common example of this. When you log in, server creates a session. That session stores who you are. Every next request, server checks that session and responds accordingly. Server is keeping your state.&lt;/p&gt;

&lt;p&gt;This works perfectly fine for single server. One server, one memory, no confusion.&lt;/p&gt;

&lt;p&gt;But when you add more servers, problem starts. Each server has its own memory. They do not share it. So if Server A created your session and Server B receives your next request, Server B has no idea who you are.&lt;/p&gt;

&lt;p&gt;That is the stateful problem in distributed systems.&lt;/p&gt;

&lt;p&gt;Some common examples of stateful systems:&lt;/p&gt;

&lt;p&gt;Laravel and PHP session based authentication. WebSocket connections to tracks connection state. Online multiplayer games to remembers player position and score.&lt;/p&gt;

&lt;p&gt;Stateful systems are not wrong. They are just not built for horizontal scaling.&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%2Fl9uj6epc4w106azjmpi6.png" 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%2Fl9uj6epc4w106azjmpi6.png" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a Stateless System?
&lt;/h3&gt;

&lt;p&gt;A stateless system does not remember anything. It treat every request as new and every request must carry all the information needed to verify and process it.&lt;/p&gt;

&lt;p&gt;JWT is the most common example of this. When you log in, server creates a token. That token contains your identity, your role, expiry time. Everything. Server does not store anything. Next request you send, you attach this token. Server reads the token, verifies it and responds. No memory needed.&lt;/p&gt;

&lt;p&gt;Any server can handle any request. Server A, Server B, Server C. It does not matter. Every request itself have all the required information.&lt;/p&gt;

&lt;p&gt;This is why stateless systems scale so well. You can add 10 servers or 100 servers. Every server can handle every request equally without having any shared memory or shared session sync.&lt;/p&gt;

&lt;p&gt;Some common examples of stateless systems:&lt;/p&gt;

&lt;p&gt;REST APIs with JWT authentication. AWS Lambda functions. Microservices communicating over HTTP.&lt;/p&gt;

&lt;p&gt;Stateless systems are not always better. But when you need to scale horizontally, stateless is the right choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;Once we identified the problem, we explained it to the client team.&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%2Fdv9jrxuylho580yabt18.png" 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%2Fdv9jrxuylho580yabt18.png" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They were surprised first. Then they laughed. All this time, three servers, load balancer, proper architecture. And the problem was just session storage. That was it.&lt;/p&gt;

&lt;p&gt;We decided to fix it in two steps.&lt;/p&gt;

&lt;p&gt;First, we moved the sessions to database. Laravel supports database as session driver out of the box. One configuration change. Now all three servers were reading and writing sessions from the same database. Server A creates session, Server B can read it. Server C can read it. No more random logouts.&lt;/p&gt;

&lt;p&gt;This was a quick fix. It worked. But we knew it was not the final solution. Every request was now hitting the database to validate the session. That adds load on database. Not a good idea for scale.&lt;/p&gt;

&lt;p&gt;So we planned the second step.&lt;/p&gt;

&lt;p&gt;We replaced session based authentication with JWT. Server creates a JWT token on login. Token goes to the client as response and client sends the token with every requests. Server verifies it and responds. No database call needed for validation. No session storage needed. Completely stateless.&lt;/p&gt;

&lt;p&gt;But we did not stop here.&lt;/p&gt;

&lt;p&gt;The client had multiple applications. Web application, student app, teacher app and many more. Each app had its own login with separate unique sessions and separate auth. We saw an opportunity to fix this properly.&lt;/p&gt;

&lt;p&gt;We built a SSO. Single Sign On. One central authentication server to authenticate users on all applications through it. Login once, access everything.&lt;/p&gt;

&lt;p&gt;We deployed SSO on a separate server with JWT. Now it was Stateless, Horizontally scalable and ready for any load.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;p&gt;Once SSO was ready, we did not go live directly.&lt;/p&gt;

&lt;p&gt;We tested it with JMeter first and simulated thousands of concurrent users hitting the system.&lt;/p&gt;

&lt;p&gt;We test it on Login, dashboard, fee management, homework and other endpoints. Everything worked. Not a single failure. No more random logouts and No session errors. Every request was going to right place.&lt;/p&gt;

&lt;p&gt;After this testing, we went to the real users.&lt;/p&gt;

&lt;p&gt;We contacted the students, teachers and school staff who had complained earlier and asked them to use the beta system. We collected their feedback one by one and everyone was happy with new system. No one faced any random logouts and system was working fine.&lt;/p&gt;

&lt;h3&gt;
  
  
  SSO Integration
&lt;/h3&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%2Fkck9siwgegsuprbon7xl.png" 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%2Fkck9siwgegsuprbon7xl.png" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once testing was done, we started integrating SSO with all client applications.&lt;/p&gt;

&lt;p&gt;Web application was first, then student app, then teacher app and so on. One by one, we replaced their existing auth with our SSO. Every application was now authenticating through one central SSO server. Each system had same JWT token and same stateless flow.&lt;/p&gt;

&lt;p&gt;The client had many schools and institutions onboarded. All of them were now using the same SSO. One login for everything.&lt;/p&gt;

&lt;p&gt;This also opened new possibilities for the client. Adding a new application in future was easy now. Just integrate with SSO and authentication is done. No need to build auth from scratch every time, just few lines of code make authentication ready.&lt;/p&gt;

&lt;p&gt;The system that was failing with 1000 concurrent users was now ready to handle much more. We did not added more servers, just fixed the root cause. Stateless architecture with central auth.&lt;/p&gt;

&lt;p&gt;If you want to read about what happened next with this system, I have written about it in my article on the &lt;a href="https://dev.to/deepakinsights/the-thundering-herd-problem-4i0k-temp-slug-7865828"&gt;Thundering Herd Problem&lt;/a&gt;. That story starts exactly where this one ends and teach you how a Perfect System can fail.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;That 2020 incident taught me more than any course or tutorial ever did.&lt;/p&gt;

&lt;p&gt;We had a perfectly designed system with three servers and load balancer. Everything correct and still it was failing. It was not because of bad architecture, but because of one small configuration that nobody thought about.&lt;/p&gt;

&lt;p&gt;Session storage.&lt;/p&gt;

&lt;p&gt;That is the thing about system design. You can design a perfect system, but still can miss one small detail that breaks the system. This is why every decision matters and need a careful consideration. Where you store sessions, how you authenticate users, and how your servers communicate. Every small thing has an impact at scale.&lt;/p&gt;

&lt;p&gt;If you are building a system today with multiple servers, ask yourself one question. Is my authentication stateful or stateless? If it is stateful, make sure your sessions are shared. Database, Redis, anything. Just not local server storage.&lt;/p&gt;

&lt;p&gt;And if you are planning to scale, move to stateless. JWT, SSO, whatever fits your use case. Your will thank yourself in future self for this decision.&lt;/p&gt;

&lt;p&gt;The guard will retire someday. Make sure your system does not depend on his memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Continue the Journey with more articles
&lt;/h3&gt;

&lt;p&gt;Still on the platform and enjoyed this ride? Here are more system design trains to catch:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to/deepakinsights/kafka-explained-like-youre-5-296o-temp-slug-1718432"&gt;Kafka Explained Like You’re 5&lt;/a&gt;: How I finally understood Kafka after years of avoiding it.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/deepakinsights/the-thundering-herd-problem-4i0k-temp-slug-7865828"&gt;The Thundering Herd Problem&lt;/a&gt;: What happens when 25,000 students hit my system at the same time.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/deepakinsights/message-queue-in-system-design-25pc-temp-slug-1504810"&gt;Message Queue in System Design&lt;/a&gt;: How my server crashed in 60 seconds and what I learned from it.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/deepakinsights/cache-strategies-in-distributed-systems-4bi0-temp-slug-9876529"&gt;Cache Strategies in Distributed Systems&lt;/a&gt;: The day our cache expired and 25,000 students lost their exam.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Looking for more? All articles are available on my &lt;a href="https://deepakinsights.medium.com/" rel="noopener noreferrer"&gt;Medium profile&lt;/a&gt; and many are coming soon. &lt;strong&gt;Follow or subscribe&lt;/strong&gt; to get notified when the next one drops.&lt;/p&gt;

</description>
      <category>authentication</category>
      <category>architecture</category>
      <category>systemdesignconcepts</category>
      <category>jwt</category>
    </item>
    <item>
      <title>Kafka Explained Like You’re 5</title>
      <dc:creator>Deepak Singh Solanki</dc:creator>
      <pubDate>Sun, 29 Mar 2026 17:52:54 +0000</pubDate>
      <link>https://dev.to/deepakinsights/kafka-explained-like-youre-5-25bp</link>
      <guid>https://dev.to/deepakinsights/kafka-explained-like-youre-5-25bp</guid>
      <description>&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%2Fo6wleqt0uzlpqdxu50on.png" 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%2Fo6wleqt0uzlpqdxu50on.png" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kafka is not a new name. It has been around for years. Every architecture blog, every system design video, every discussion in colleague and developer circle, Kafka comes up. I heard about it many times. But never really stopped to learn it. I never went beyond the surface. Not even once.&lt;/p&gt;

&lt;p&gt;I won’t lie. I always thought Kafka was just another &lt;strong&gt;message queue&lt;/strong&gt;. A fancier &lt;strong&gt;RabbitMQ&lt;/strong&gt;. Something I will learn “someday.” That someday never came.&lt;/p&gt;

&lt;p&gt;Then I joined a System Design Cohort led by Hitesh Choudhary and Piyush Garg on ChaiCode. One evening, Piyush sir started explaining Kafka.&lt;/p&gt;

&lt;p&gt;I was listening. But my mind was doing something else.&lt;/p&gt;

&lt;p&gt;Steve Jobs once said: “You can’t connect the dots looking forward; you can only connect them looking backward.”&lt;/p&gt;

&lt;p&gt;That evening, my mind was connecting dots backward to the Indian railway station.&lt;/p&gt;

&lt;p&gt;We all have been to railway station at least once in life and if you have, you know that feeling. It is not calm. It is not organised. Somehow it just work. Nobody is managing you personally. No one is telling each passenger where to go. Still, people loves to travel in trains. They reach where they have to go. The whole madness somehow just keep running every single day.&lt;/p&gt;

&lt;p&gt;I was surprised that Kafka was solving the similar problem in software world.&lt;/p&gt;

&lt;p&gt;Piyush sir was explaining Kafka in class and I was seeing every single thing play out at that station in my mind. For the first time, Kafka start making sense to me.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Kafka Exists: The Problem First
&lt;/h3&gt;

&lt;p&gt;Before I tell you what Kafka is, let me tell you why it even exist.&lt;/p&gt;

&lt;p&gt;Everyone are using &lt;strong&gt;IRCTC&lt;/strong&gt; for train ticket booking. You definitely had an experience of &lt;strong&gt;tatkal booking&lt;/strong&gt; chaos. Everyone wants to book ticket at same time. You finally get that booking confirmation. But did you ever wonder what all happen in that one second? Money got deducted from your account. Seats got booked for you. A message land on your phone. Your ticket was ready somewhere in their system. PNR got updated. All of this happen in few seconds. Not for you alone. For lakhs of people at same time.&lt;/p&gt;

&lt;p&gt;Now what if any one of these steps fail or slow down or miss the request? This kind of simultaneous load is something I wrote about earlier — it is called the &lt;a href="https://dev.to/deepakinsights/the-thundering-herd-problem-4i0k-temp-slug-7865828"&gt;&lt;strong&gt;Thundering Herd Problem&lt;/strong&gt;&lt;/a&gt;.&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%2Fp436t11ojvxuq37g8f85.jpeg" 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%2Fp436t11ojvxuq37g8f85.jpeg" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That is the exact problem Kafka was built to solve.&lt;/p&gt;

&lt;p&gt;This is the problem. Modern applications are not simple anymore. They are not one service talking to one other service. They are dozens of services, each generating events, each needing to talk to each other, all at once.&lt;/p&gt;

&lt;p&gt;And here is where most people make a mistake. They think Kafka is just a &lt;a href="https://dev.to/deepakinsights/message-queue-in-system-design-25pc-temp-slug-1504810"&gt;&lt;strong&gt;message queue&lt;/strong&gt;&lt;/a&gt;. I thought the same.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It is not.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://dev.to/deepakinsights/message-queue-in-system-design-25pc-temp-slug-1504810"&gt;&lt;strong&gt;message queue&lt;/strong&gt;&lt;/a&gt; is like a postman. One sender, one receiver, message delivered and gone. Simple.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kafka is a message broker.&lt;/strong&gt; Not a queue. It sit between all your services like a central hub. Many things pushing data into it at same time. Many others pulling from it. Kafka store every message. Same message, multiple services can read it. Nothing get lost in between.&lt;/p&gt;

&lt;p&gt;That difference, trust me, it matter a lot.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kafka is the Railway Station
&lt;/h3&gt;

&lt;p&gt;Close your eyes for a second.&lt;/p&gt;

&lt;p&gt;You are standing at a busy railway station. Not a small one. A big one. Hundreds of passengers arriving every minute. Some coming from Jaipur. Some going to Mumbai. Some waiting for a local train. Everyone with a different destination.&lt;/p&gt;

&lt;p&gt;We all have stood at a railway station at some point. That chaos is not new to us. You are looking for your platform, someone is running with luggage, someone is asking for directions, tea vendor is shouting from corner. Nobody is in charge of you personally. Still you reach. Still everyone reach.&lt;/p&gt;

&lt;p&gt;Now think about this. That station never stop working. Too many passengers? It handle them. Someone miss their train? Another one is coming. No matter how crowded it get, station just keep doing its job.&lt;/p&gt;

&lt;p&gt;That is exactly what Kafka does for your application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kafka is that station.&lt;/strong&gt; Every message in your system is like that passenger who need to reach somewhere. Station manage thousands of people without losing single one. Kafka do exactly that for your software.&lt;/p&gt;

&lt;p&gt;Everything connect to Kafka. Every message pass through it and from there, each message reach exactly where it need to go.&lt;/p&gt;

&lt;h3&gt;
  
  
  Producer: Who Sends the Message
&lt;/h3&gt;

&lt;p&gt;We all have reached a railway station at some point and we all had someone who drop us there. Could be father, friend, or just an auto driver. Once you are inside the station, their job is done. They don’t come with you. They don’t worry about where you will go next.&lt;/p&gt;

&lt;p&gt;In Kafka, that person is called a &lt;strong&gt;Producer&lt;/strong&gt;. Any service that generate and send message to Kafka is a &lt;strong&gt;Producer&lt;/strong&gt;. Your payment service send a payment event. Your app send a booking request. It does not matter who send it. Once message reach Kafka, producer job is finish.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Producer&lt;/strong&gt; don’t care what happens next. Who reads the message. When they read it. That is not producer’s problem. Producer completed his job the moment message reach Kafka.&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%2F9u7uz8t2l5wmy1xd5ejk.png" 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%2F9u7uz8t2l5wmy1xd5ejk.png" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Topics: The Platforms
&lt;/h3&gt;

&lt;p&gt;You are inside the station now. You are that message, remember? First thing you look for is your platform. Not randomly. You check your ticket. Platform 4. That is where your train is. Every passenger go to their specific platform. Nobody mix up.&lt;/p&gt;

&lt;p&gt;In Kafka, these platforms are called &lt;strong&gt;Topics&lt;/strong&gt;. Every message go to a specific &lt;strong&gt;topic&lt;/strong&gt;. Order messages go to orders topic. Payment messages go to payments topic. Nobody mix up there either.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;Topic&lt;/strong&gt; is a category. Think of it as a named channel. Order related messages always find their own place. Payment messages find theirs. Notifications find theirs. Nobody land in wrong place.&lt;/p&gt;

&lt;p&gt;Think of it this way: producer does not just throw message into Kafka randomly. It send message to a specific &lt;strong&gt;topic&lt;/strong&gt;. Just like passenger go to specific platform.&lt;/p&gt;

&lt;p&gt;Order related messages will always find the &lt;strong&gt;“orders”&lt;/strong&gt; platform. Payment messages will always find &lt;strong&gt;“payments”&lt;/strong&gt;. No mixing. No confusion.&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%2F7gnfqy3yf31kjuzfrhv7.png" 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%2F7gnfqy3yf31kjuzfrhv7.png" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Partitions: The Bogies
&lt;/h3&gt;

&lt;p&gt;Now here is where it get really interesting.&lt;/p&gt;

&lt;p&gt;You found your platform. Train is right there. But when you step closer, you notice something. Train is not just one big space. It is divided into bogies. S1, S2, S3, A1, B2. Each bogie carries different passengers. Together, they all go to same destination.&lt;/p&gt;

&lt;p&gt;In Kafka, these bogies are called &lt;strong&gt;Partitions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;One &lt;strong&gt;Topic&lt;/strong&gt; can have multiple &lt;strong&gt;Partitions&lt;/strong&gt;. They belongs to the same category, but work is split into smaller lanes. This is where Kafka actually get its real power from.&lt;/p&gt;

&lt;p&gt;But here is the important thing Piyush sir explained that day. This is what change everything for me.&lt;/p&gt;

&lt;p&gt;Why we need these partitions? Why not just one big bogie?&lt;/p&gt;

&lt;p&gt;We all know Indian train classes. General, Sleeper, Third AC, Second AC and First AC. Each class has its own coach. General passengers never sit in First AC coach. First AC passengers never end up in Sleeper. Everyone belong to their own coach. That is just how it work.&lt;/p&gt;

&lt;p&gt;Kafka follow same rule. &lt;strong&gt;Related messages always go to same partition.&lt;/strong&gt; Same order ID will always goto same partition. The sequence stay intact. Every time.&lt;/p&gt;

&lt;p&gt;Because there are multiple partitions, multiple consumers can work in parallel. More partitions, more speed. That is how Kafka scale without breaking the order.&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%2Ftjwmop1rnqaxg5hkkwe9.png" 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%2Ftjwmop1rnqaxg5hkkwe9.png" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Consumers: Who Receives the Message
&lt;/h3&gt;

&lt;p&gt;Every passenger on that train is going somewhere. Someone is waiting at the destination. Could be a family member standing at exit gate. Could be a friend who came to pick up. Could be a colleague. Their job is simple. Receive and take action.&lt;/p&gt;

&lt;p&gt;In Kafka, that person is called a &lt;strong&gt;Consumer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;Consumer&lt;/strong&gt; is any service that read messages from Kafka. Your notification service consume the order event and send push notification. Your analytics service consume the same event and update dashboard. Your inventory service consume it and reduce stock count.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consumer&lt;/strong&gt; sit and wait. When message arrive in their topic, they read it. They process it. They take action.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Producer&lt;/strong&gt; send. &lt;strong&gt;Kafka&lt;/strong&gt; hold. &lt;strong&gt;Consumer&lt;/strong&gt; receive. That is the basic flow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consumer Groups: Sharing the Work
&lt;/h3&gt;

&lt;p&gt;We all have travelled in a train with a big group at some point. Could be a family trip, college friends, or office team. Everyone board same train. But when train reach destination, everyone scatter. Some head to hotel. Some go to relatives place. Some go directly to the event. Nobody wait for each other. Each group know where they have to go.&lt;/p&gt;

&lt;p&gt;In Kafka, this is called a &lt;strong&gt;Consumer Group&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;Consumer Group&lt;/strong&gt; is a set of consumers that work together to read from a topic and here is what make it powerful: each partition is read by only one consumer within a group. Work is divide evenly. No two consumers in same group read the same message.&lt;/p&gt;

&lt;p&gt;So if your “orders” topic has 4 partitions, and you have 4 consumers in a group, each consumer handle one partition. &lt;strong&gt;Parallel processing.&lt;/strong&gt; Fast. Efficient.&lt;/p&gt;

&lt;p&gt;But now here is something even more interesting.&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%2F1tyq9dkhfddfzgozhtnw.png" 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%2F1tyq9dkhfddfzgozhtnw.png" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can have &lt;strong&gt;multiple Consumer Groups&lt;/strong&gt; reading the same topic completely independently.&lt;/p&gt;

&lt;p&gt;Your notification service is reading from orders topic. Your analytics service is also reading from same orders topic. Both get every message. One send notification. Other update the dashboard. Neither know about each other. Neither disturb each other.&lt;/p&gt;

&lt;p&gt;Same train. Different families. Each going where they need to go.&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%2Fydr6mpgh0s4vho1suiuy.png" 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%2Fydr6mpgh0s4vho1suiuy.png" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Kafka is Fast and Scalable
&lt;/h3&gt;

&lt;p&gt;One last thing before we wrap this up.&lt;/p&gt;

&lt;p&gt;How does a big railway station handle lakhs of passengers every single day without shutting down?&lt;/p&gt;

&lt;p&gt;Simple. It don’t rely on one platform. One train. One bogie. It has many platforms running in parallel. Many trains on each platform. Many bogies on each train. Work is spread out.&lt;/p&gt;

&lt;p&gt;Kafka work the same way.&lt;/p&gt;

&lt;p&gt;More &lt;strong&gt;topics&lt;/strong&gt; for more categories. More &lt;strong&gt;partitions&lt;/strong&gt; for more parallel processing. More &lt;strong&gt;consumers&lt;/strong&gt; in a group to share the load. You need to handle more messages? Add more partitions. Add more consumers. The system &lt;strong&gt;scale horizontally&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;No single point doing all the work. No bottleneck. No crash.&lt;/p&gt;

&lt;p&gt;Any application that survive millions of events per second, trust me, has something like Kafka running quietly in the background doing this job.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion: You Are the Message
&lt;/h3&gt;

&lt;p&gt;So that evening in cohort class, dots finally connected for me. Backward. Just like Steve Jobs said.&lt;/p&gt;

&lt;p&gt;Kafka is not just another &lt;strong&gt;message queue&lt;/strong&gt; , it is a &lt;strong&gt;message broker&lt;/strong&gt;. A central station for your entire application. Scale does not break. Order does not get lost. Multiple teams can read same data. Nobody disturb anyone else.&lt;/p&gt;

&lt;p&gt;Everything we went through today, &lt;strong&gt;Producers&lt;/strong&gt; , &lt;strong&gt;Topics&lt;/strong&gt; , &lt;strong&gt;Partitions&lt;/strong&gt; , &lt;strong&gt;Consumers&lt;/strong&gt; , &lt;strong&gt;Consumer Groups&lt;/strong&gt; , that whole journey, it was all happening at that one busy station.&lt;/p&gt;

&lt;p&gt;So go back to that station one last time.&lt;/p&gt;

&lt;p&gt;This time do not stand outside watching. Step in.&lt;/p&gt;

&lt;p&gt;You are not standing outside anymore. You are inside. You are that passenger. &lt;strong&gt;You are the message.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Someone dropped you at the station. That was your &lt;strong&gt;Producer&lt;/strong&gt;. You walked to your platform. That is your &lt;strong&gt;Topic&lt;/strong&gt;. You boarded your coach. That is your &lt;strong&gt;Partition&lt;/strong&gt;. You found your seat. That is your &lt;strong&gt;offset&lt;/strong&gt; , your exact position, your order guaranteed.&lt;/p&gt;

&lt;p&gt;The train moves. It reaches the destination. Someone is waiting for you there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That is Kafka.&lt;/strong&gt;&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%2F726attnxrdn34yck3mog.png" 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%2F726attnxrdn34yck3mog.png" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next time someone says “we use Kafka for event streaming”, you will smile. Because this time, you know exactly what is happening inside that station.&lt;/p&gt;

&lt;h3&gt;
  
  
  Continue the Journey with more articles
&lt;/h3&gt;

&lt;p&gt;Still on the platform and enjoyed this ride? Here are more system design trains to catch:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to/deepakinsights/the-thundering-herd-problem-4i0k-temp-slug-7865828"&gt;The Thundering Herd Problem&lt;/a&gt;: What happens when 25,000 students hit my system at the same time.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/deepakinsights/message-queue-in-system-design-25pc-temp-slug-1504810"&gt;Message Queue in System Design&lt;/a&gt;: How my server crashed in 60 seconds and what I learned from it.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/deepakinsights/cache-strategies-in-distributed-systems-4bi0-temp-slug-9876529"&gt;Cache Strategies in Distributed Systems&lt;/a&gt;: The day our cache expired and 25,000 students lost their exam.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Looking for more? All articles are available on my &lt;a href="https://deepakinsights.medium.com/" rel="noopener noreferrer"&gt;Medium profile&lt;/a&gt; and many are coming soon. &lt;strong&gt;Follow or subscribe&lt;/strong&gt; to get notified when the next one drops.&lt;/p&gt;

</description>
      <category>kafka</category>
      <category>systemdesignconcepts</category>
      <category>architecture</category>
      <category>distributedsystems</category>
    </item>
    <item>
      <title>Message Queue in System Design</title>
      <dc:creator>Deepak Singh Solanki</dc:creator>
      <pubDate>Sat, 14 Mar 2026 07:02:52 +0000</pubDate>
      <link>https://dev.to/deepakinsights/message-queue-in-system-design-3ioh</link>
      <guid>https://dev.to/deepakinsights/message-queue-in-system-design-3ioh</guid>
      <description>&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%2Fxhvsw9b1d7xfbqclx6uz.jpeg" 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%2Fxhvsw9b1d7xfbqclx6uz.jpeg" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Day My Server Gave Up in 60 Seconds
&lt;/h3&gt;

&lt;p&gt;The Day My Server Gave Up in 60 Seconds&lt;/p&gt;

&lt;p&gt;In April 2018, it was our project launch day. I was working on a project for the last 6 months, spending many restless nights to shape it into something I was truly proud of.&lt;/p&gt;

&lt;p&gt;We launched at 9:30 AM, and by 9:31 AM, the server had crashed.&lt;/p&gt;

&lt;p&gt;Everyone was shocked. No one had a clue what had just happened. I still remember the silence in the room. It was a horrible, heavy silence when something went wrong in front of everyone. Later, we came to know that thousands of OTP requests were hitting our system at the same time. And we were handling all of them one by one. Synchronously. Imagine a single ticket counter and an entire stadium full of people.&lt;/p&gt;

&lt;p&gt;That one minute, it changed everything for me.&lt;/p&gt;

&lt;p&gt;And the solution? A queue. Same thing you stand in while buying a movie ticket. The same one you curse while waiting for your movie ticket. But inside a system, it decide difference between a crash and calm.&lt;/p&gt;

&lt;p&gt;That day in 2018, I wished I had known this earlier. Now you will.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Servers Break Under Pressure
&lt;/h3&gt;

&lt;p&gt;Think about WhatsApp for a second.&lt;/p&gt;

&lt;p&gt;Every second, millions of people are sending messages to each other. It may be a birthday wishes, memes, voice notes, and office updates. Every single message is a request to handle for WhatsApp’s servers.&lt;/p&gt;

&lt;p&gt;Now imagine you are the server.&lt;/p&gt;

&lt;p&gt;One request comes in, it’s easy to handle. Ten requests, it’s still fine. A thousand requests make it hard. A million requests in the same second make you collapse.&lt;/p&gt;

&lt;p&gt;WhatsApp isn’t the only the one who are facing this problem, all popular apps face it, and you may face the same in the future. The day your app goes from 100 users to 100,000 users, an influencer shares your product, or the day your sale goes live. Suddenly, your server is not handling requests; it is drowning in them.&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%2Fuw8bb5gw6y8msbln5xv6.jpeg" 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%2Fuw8bb5gw6y8msbln5xv6.jpeg" width="800" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Do you know the worst part? Most servers are built to handle requests simultaneously i.e. one by one. It finishes the first request, then moves to the next. It works fine until it gets high traffic. Once the moment traffic spikes, everything slows down, requests pile up, and eventually, the server gives up.&lt;/p&gt;

&lt;p&gt;I know this feeling as I lived it in April 2018.&lt;/p&gt;

&lt;p&gt;Now think about the real question, how do apps like WhatsApp, Instagram, and BookMyShow handle this without breaking? How does their system stay calm and running even millions of people are using it continuously?&lt;/p&gt;

&lt;p&gt;That’s exactly what we are going to discuss hereafter.&lt;/p&gt;

&lt;h3&gt;
  
  
  So What Exactly Saved My System?
&lt;/h3&gt;

&lt;p&gt;We all remember those days when our parents or grandparents used to write letters. Postman collects these letters and everytime deliver the letter to destination. We always know that the letter always reached, without tracking, and without any confirmation.&lt;/p&gt;

&lt;p&gt;A message queue works the same way.&lt;/p&gt;

&lt;p&gt;In a system, one part of your application writes a message and drops it into the queue, just like giving a letter to the postman. Another part of your application picks it up from the queue and processes it, just like the person receiving the letter. Neither side needs to talk to the other directly. Neither side needs to wait for the other.&lt;/p&gt;

&lt;p&gt;This is what developers mean when they say “decoupled architecture.” Neither side knows the other exists and never waits for the other. If one side is busy or temporarily down, then the message just sits patiently in the queue until someone picks it up.&lt;/p&gt;

&lt;p&gt;You can consider a message queue as a waiting room for data. Requests are taken one by one. No chaos. No crashes. No one stepping on each other’s toes.&lt;/p&gt;

&lt;p&gt;Remember about the OTP crash in 2018? A message queue could have avoid it completely.&lt;/p&gt;

&lt;h3&gt;
  
  
  Meet the Five Players Behind Every Message
&lt;/h3&gt;

&lt;p&gt;Before we deep dive more, let me first introduce you to the five key players that make this work. We will stick with our postman story, it makes everything click faster.&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%2Fj0gceo41ajwxe3uerwdo.jpeg" 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%2Fj0gceo41ajwxe3uerwdo.jpeg" width="800" height="542"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Producer/Publisher: The Letter Writer&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
We never worried about how our letter would reach. We wrote it, and handed it over to the postman. A producer works exectly the same, it creates a message and drops it into the queue. Producer completed his job. Every message contains the actual data it want to send (payload) and some background details like when it was created and how urgent it is (metadata).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Queue: The Post Office&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The postman does not deliver letters immediately. It takes time. You can consider it as doctor’s clinic, where a receptionist that takes your information and ask you to wait until someone is free to help. Queue never do any processing, never read the message, it just keep the message safely stored.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Consumer/Subscriber: The Letter Receiver&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Think about receiving a new iPhone parcel. You walk to door to receive the parcel, open it and start clicking picture. The consumer works the same. It connect to the queue to consume a message, then it puts message to work, processing it, storing it, or triggering whatever needs to happen next. The things finally happens here. Some systems have one consumer reading the queue. Others have ten. Depends on how much traffic your system handles.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Broker/Queue Manager: The Postman&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Without the postman, letters pile up, and never deliver. The broker is responsible for receiving message from the producer and drops it in the right queue. It make sure that the correct consumer picks it up. If a message lost? He retries. A wrong destination? He reroutes. He manage everything, no one can bypass it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Message: The Letter Itself&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Every letter has two things. What’s written inside, that is your actual data, we call it payload. And the envelope, the address, date, stamp, all the details written outside. We call that metadata. The metadata tells the system about its origin, destination &amp;amp; how urgent it is.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Complete Journey of a Single Message
&lt;/h3&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%2Ffmvzfd4afqe98jj1gxe3.jpeg" 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%2Ffmvzfd4afqe98jj1gxe3.jpeg" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let’s understand about these players work together. We will follow one message start to finish, the same way a letter travel from origin to destination.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Message Creation&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Your wote the letter and address, it now ready for post. Similarly, the producer creates a message with the actual data (payload) and some extra details like timestamp and priority (metadata) and the message is ready to travel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Message Enqueue&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
You hands it to the postman. The producer send the message to the queue and move forward. He did not worried about checking and waiting for furture communication. The message wait there until someone picks it up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Message Storage&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The postman collect letters and keep it in bag. Depending upon the system requirement, queue stores the message in memory (if speed matters), or on disk (if you can’t risk losing it).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Message Dequeue&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The postman reaches the destination and knocks on the door. The consumer grabs the message and starts working on it. Some systems process one message at a time. Others throw ten consumers into the queue simultaneously. Both work fine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Acknowledgment&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The receiver signs for the delivery. The consumer sends a signal back saying the message was processed successfully. Acknowledgment is most important, never skip it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6: Message Deletion&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Once getting delivery confirmation, the broker removes the message from the queue permanently. Similarly, you stop tracking you parcel once it recieved. If no confirmation comes back, the It keep retries until someone actually finishes the job. The message stays safe and never lost.&lt;/p&gt;

&lt;p&gt;These six steps makes the full journey. I keep thinking about that day. If message queue was there in 2018, those OTP requests would have just waited their turn. No pile up. No crash. This time, no silence in the room. Just a big celebration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Not All Queues Work the Same Way
&lt;/h3&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%2Fcdn-images-1.medium.com%2Fmax%2F839%2F1%2AgJgbCWtU0lpTtrn5WdFifQ.png" 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%2Fcdn-images-1.medium.com%2Fmax%2F839%2F1%2AgJgbCWtU0lpTtrn5WdFifQ.png" width="800" height="593"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Different queues solves different problems. Here are the four types you’ll come across most often.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Point-to-Point (P2P) Queue&lt;/strong&gt;
One sender and one receiver that’ the Point-to-Point queue in the system. Even if multiple consumers are listening, still only one gets each message. Once it’s processed and acknowledged, it’s gone. Good for tasks that should run exactly once, like charging a payment or sending an invoice.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;2. Publish/Subscribe (Pub/Sub) Queue&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
One sender. Many receivers. That’s it. Producer drop a message to a topic and forget about it. Every subscriber of that topic get their own copy. The sender has no idea who’s listening and doesn’t need to. When you place a Swiggy order that one event notify your app, the restaurant, and the delivery partner all at once. That’s Pub/Sub.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Priority Queue&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Some messages are more important than others. A payment failure alert can’t wait behind a promotional email? Priority queue solve this problem. You assign urgency. Critical goes first and the rest waits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Dead Letter Queue (DLQ)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Sometimes a message just refuse to process. Wrong format, failed retries, some unexpected error. These broken messages, if you leave them in main queue, they block everything else. So system moves them to a separate place, we call it Dead Letter Queue.&lt;/p&gt;

&lt;p&gt;I have used this more times than I want to admit. It let you investigate what went wrong, fix it, and move on. Main queue never get disturbed.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;You Are Already Using This Every Day&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Message queues are already part of our daily life. You just didn’t realize it. Any app that survive high traffic, trust me, has a queue somewhere in background doing its job quietly.&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%2Fcdn-images-1.medium.com%2Fmax%2F971%2F1%2AFOBSOdNaP1OCeEa55Lm7Sg.jpeg" 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%2Fcdn-images-1.medium.com%2Fmax%2F971%2F1%2AFOBSOdNaP1OCeEa55Lm7Sg.jpeg" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. WhatsApp Messages&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Send a message, get one tick, then two. That first tick indicate that your message reached to the queue. The second ensure that it reached your friend. That small delay shows that a message queue is working in background to deliver this mesage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Swiggy / Zomato Orders&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Place an order, and within seconds, the restaurant gets a notification, the delivery partner gets assigned, and you get a confirmation. That’s not happening simultaneously. Queue that your order and route it to each party one step at a time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. OTP Messages&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Sometimes it takes time for the OTP to arrive, because thousands of users requested it at the same time. The system adds every request to a queue and sends them out in order. In 2018, we didn’t have this. Our system tried to process all OTP requests at once, and the server collapsed in 60 seconds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Email Notifications&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A company sends promotional email to five million users, but they never hit send for all five million at once. Every email goes into queue first, then process in batches. Steady and Controlled. No spike.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. BookMyShow Ticket Booking&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
IPL ticket available on BookMyShow. Million people trying to book ticket at exact same second. Without the queue, server crash in seconds. With queue, requests just line up. Some people still don’t get tickets, but atleast the site don’t crash. That’s the win.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Which Tool Should You Actually Start With?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;After the 2018 crash, I start learning about the message queue tools. I have personally worked with RabbitMQ and SQS. Both are solid. But there are other options too depending on your use case.&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%2Fcdn-images-1.medium.com%2Fmax%2F855%2F1%2AxTfUP8J5CbB--u8MoWy7Ig.jpeg" 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%2Fcdn-images-1.medium.com%2Fmax%2F855%2F1%2AxTfUP8J5CbB--u8MoWy7Ig.jpeg" width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. RabbitMQ: Start Here&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Simple. Well documented. Easy to run locally. I built my first message queue with RabbitMQ, and honestly it taught me a lot. If you are just starting out, this is where you begin. Works well for email and notification systems. Small to medium projects with flexible routing? RabbitMQ is good fit for that. Not as powerful as Kafka. Not as managed as SQS. But open source, and it adapt to almost anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Apache Kafka: When Scale Gets Serious&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Kafka is different. You throw millions of messages per second at it. It just keep going. Don’t even slow down. Swiggy, Ola, real time analytics systems, all running Kafka somewhere in background. It take time to learn. But once you understand it, you see why big systems trust it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Amazon SQS: For AWS Teams&lt;/strong&gt; You don’t need to manage any servers and you don’t have setup headaches. AWS will do it for you. If you’re already on AWS, SQS is the best choice. You just need to pay for what you use and keep scaling automatically. Let AWS worry about the infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. IBM MQ: For Systems That Can’t Lose Messages&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Banks and large enterprises trust this. Because in financial systems, losing even single message is not an option. Yes it’s expensive. Yes it’s complex. But when money is involved, that tradeoff make complete sense.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Apache ActiveMQ (Artemis): Middle Ground&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Working on small or medium project with some routing needs? ActiveMQ is a good fit for that. Not as powerful as Kafka. Not as managed as SQS. But open source, and it adapt to almost anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. NATS: For Speed&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Lightweight yet extremely fast. If your system needs low latency and doesn’t need to persist messages, NATS is worth a look.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Powerful, But Not Without a Cost&lt;/strong&gt;
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;p&gt;Message queues do a lot more than just prevent crashes. Here’s what you actually gain.&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%2Fcdn-images-1.medium.com%2Fmax%2F979%2F1%2A7kc61sES-6x1NM44kZW-lw.jpeg" 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%2Fcdn-images-1.medium.com%2Fmax%2F979%2F1%2A7kc61sES-6x1NM44kZW-lw.jpeg" width="800" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Decoupling&lt;/strong&gt; : Producer and consumer, they never need to know each other exist. You want to update one side? Go ahead. Replace it? Fine. Scale it? No problem. Other side never get affected. I have seen this save so much pain in teams where multiple developers are working on same system. Everyone work independently. No one stepping on each other’s toes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scalability&lt;/strong&gt; : Sudden traffic spike? Add more consumers. They pick up from queue on their own. Load gets shared automatically. You don’t even need to redeploy anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reliability&lt;/strong&gt; : If consumer crashes mid-processing, then the message stays in the queue. When it recovers, it picks up where it left off. We learned this the hard way in 2018.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Async Processing&lt;/strong&gt; : The producer drops message and keep moving. Don’t wait for anyone. User get response immediately. Background task finish on its own later. This is why your app feel faster than it actually is.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tradeoffs
&lt;/h3&gt;

&lt;p&gt;The message queues are not the perfect solution. They come with real costs.&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%2Fcdn-images-1.medium.com%2Fmax%2F984%2F1%2Abu8zrF-Xns7LWAS4fE8NgA.jpeg" 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%2Fcdn-images-1.medium.com%2Fmax%2F984%2F1%2Abu8zrF-Xns7LWAS4fE8NgA.jpeg" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Complexity&lt;/strong&gt; : A message queue is one more thing to manage. Queue, broker, consumers, all running separately alongside your actual application. For small projects, honestly ask yourself, is this complexity really worth it? Sometimes simple is better.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Debugging is Hard&lt;/strong&gt; : In synchronous systems debugging are easy, so when something breaks, its easy to trace. But async systems have a different story. Its takes a time to find exact problem, when something goes wrong inside a queue. I have spent some very long nights because of this. Trust me on this one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Message Ordering&lt;/strong&gt; : Message ordering may be change in queue, because most queues don’t guarantee messages arrive in the order they were sent. If your system depends on sequence, you need to plan for this upfront.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Extra Cost&lt;/strong&gt; : More infrastructure means more money. Managed services like SQS or Kafka on Confluent aren’t free. Factor this in early.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Message Duplication&lt;/strong&gt; : If an acknowledgment gets lost, then the same message can arrive more than once. Your system needs to handle this gracefully, or you’ll process the same request twice.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What That 60 Second Crash Taught Me&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;April 2018 was embarrassing. Six months of work, a room full of people watching, and the server went down in sixty seconds.&lt;/p&gt;

&lt;p&gt;But I’m glad it happened.&lt;/p&gt;

&lt;p&gt;That one failure teach me the actual understanding about how large systems handle scale. It introduced me to message queues and honestly, it made me a much better developer than I would have been otherwise.&lt;/p&gt;

&lt;p&gt;If you’re building something that real users will touch, you need to understand this. You don’t have to start with Kafka. Start with RabbitMQ on a small side project. Build, Break and Fix. That experience will teach you more than reading about it ever could.&lt;/p&gt;

&lt;p&gt;Including this article. 😄&lt;/p&gt;

&lt;p&gt;Next time you see that single tick on WhatsApp or watch your Swiggy order get confirmed in three seconds, Don’t forgot to thank a queue.&lt;/p&gt;

</description>
      <category>systemdesignconcepts</category>
      <category>messagequeue</category>
      <category>systemdesignintervie</category>
    </item>
    <item>
      <title>Cache Strategies in Distributed Systems</title>
      <dc:creator>Deepak Singh Solanki</dc:creator>
      <pubDate>Sun, 08 Mar 2026 18:11:34 +0000</pubDate>
      <link>https://dev.to/deepakinsights/cache-strategies-in-distributed-systems-1120</link>
      <guid>https://dev.to/deepakinsights/cache-strategies-in-distributed-systems-1120</guid>
      <description>&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AbYmCQqy3-sWq_wBMj4Kxsg.png" 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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AbYmCQqy3-sWq_wBMj4Kxsg.png" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;In 2021, during a mock exam for 25,000 students, our system crashed. The reason was not just high traffic. All our cache keys expired at the same time. Every request hit the database directly. The database slowed down. The exam failed before it even started.&lt;/p&gt;

&lt;p&gt;That day taught me one thing: caching alone is not enough.&lt;/p&gt;

&lt;p&gt;In distributed systems, cache is your first line of defence. It stores frequently accessed data in high-speed memory, reduces database load, and improves response time. But if you don’t manage it properly, cache itself becomes the reason your system goes down.&lt;/p&gt;

&lt;p&gt;In this article, I will walk you through why basic TTL breaks under pressure and what I learned about TTL Jitter, Probabilistic Early Re-computation, Mutex Locking, Stale-While-Revalidate, and Cache Warming the hard way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Basic TTL Is Not Enough
&lt;/h3&gt;

&lt;p&gt;When I first started working with caching, TTL felt like a complete solution. Set an expiry time, cache refreshes automatically. Simple and clean.&lt;/p&gt;

&lt;p&gt;But here is the problem. TTL does not care about what is happening in your system. It does not know if it is 2 AM with zero traffic or an IPL match day with millions of users online. It just expires. Every single time.&lt;/p&gt;

&lt;p&gt;In a single server system, this is manageable. But in distributed systems, you are not dealing with one cache key. You are dealing with thousands of them. And when all of them share the same TTL, they all expire at the same time.&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AMKULbliIZrmY8YZxgAVx1A.png" 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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AMKULbliIZrmY8YZxgAVx1A.png" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That is exactly what happened with us. Our cache TTL was set to expire between 5 PM to 6 PM every Sunday. The same time our exam started. 25,000 students hit the system, cache expired simultaneously, and every request went straight to the database.&lt;/p&gt;

&lt;p&gt;Basic TTL has one job: expire the cache. It does that job well. But it has no strategy for what happens next. No coordination. No awareness. Just expiry.&lt;/p&gt;

&lt;p&gt;That gap is where distributed systems break.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Cache Expiry Causes Traffic Spikes
&lt;/h3&gt;

&lt;p&gt;A request comes in, server looks for data in cache, finds it, and sends the response back. The database is never involved.&lt;/p&gt;

&lt;p&gt;But what if thousands of cache keys expire together? Suddenly, every request finds an empty cache and hits the database directly. Connection pool fills up. Queries start queuing. Response time increases.&lt;/p&gt;

&lt;p&gt;Users see a slow response and start refreshing. More requests. More load. More failures. The system keeps struggling until it crashes.&lt;/p&gt;

&lt;p&gt;On our exam day, this is exactly what happened. 25,000 students hit the database directly. Students refreshed. The system could not recover in time.&lt;/p&gt;

&lt;p&gt;This chain reaction is called Thundering Herd. And basic TTL has no answer for it.&lt;/p&gt;

&lt;h3&gt;
  
  
  TTL Jitter
&lt;/h3&gt;

&lt;p&gt;Different roads get a green signal at different times to avoid all traffic moving simultaneously. If all roads get a green signal at once, it results in chaos. Same thing happens when all cache keys expire at the same time. The database gets hit by thousands of requests together and the system struggles to recover.&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AIZyH-edVtVWN43O5b4yq9g.png" 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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AIZyH-edVtVWN43O5b4yq9g.png" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;TTL Jitter solves this by adding a small random value to each cache key’s expiry time. Some keys expire a little earlier, some a little later. No two keys expire at exactly the same time. This spreads the database load across a window instead of hitting it all at once.&lt;/p&gt;

&lt;p&gt;It is a small change but it makes a big difference during high traffic events like IPL match day or a Big Billion Day sale.&lt;/p&gt;

&lt;h3&gt;
  
  
  Probabilistic Early Re-computation
&lt;/h3&gt;

&lt;p&gt;A car fuel indicator does not wait for the tank to go empty before warning you. It alerts you early, while there is still enough fuel to reach a petrol pump. You always refill it before it goes empty.&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A9AlfMWPgaXnJTX9PFpcM_w.png" 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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A9AlfMWPgaXnJTX9PFpcM_w.png" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Probabilistic Early Re-computation works the same way. Instead of waiting for a cache key to fully expire, the system starts refreshing it early. But not always. It uses a probability calculation to decide whether to trigger the refresh. The closer the cache gets to its expiry, the higher the chance of early refresh. This way, the cache is always ready before it expires, and the database never gets a sudden spike of requests.&lt;/p&gt;

&lt;p&gt;This is especially useful during high-traffic events. When millions of users are hitting the same cache key, you cannot afford to let it expire. Probabilistic Early Re-computation ensures the cache is silently refreshed in the background before expiry hits, and the thundering herd never gets a chance to start.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mutex / Cache Locking
&lt;/h3&gt;

&lt;p&gt;Imagine a busy grocery store with a single billing counter. When one customer is being billed, others wait in the queue. Nobody jumps the counter to bill themselves. One at a time, in order.&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AOfWqCiZz4uw4q5E0hHw6jQ.png" 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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AOfWqCiZz4uw4q5E0hHw6jQ.png" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mutex / Cache Locking works the same way. When cache expires, only the first request acquires the lock and hits the database to regenerate the cache. All other requests wait in the queue till the cache is ready. Once the cache is refreshed, the lock is released and all waiting requests get the data directly from the cache.&lt;/p&gt;

&lt;p&gt;One important thing. Always set an expiry on the lock. If the request that acquired the lock crashes, the lock must auto-release. Otherwise, all waiting requests will be stuck forever and your system will freeze.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stale-While-Revalidate
&lt;/h3&gt;

&lt;p&gt;The government announces a petrol price hike from today’s midnight. But you can still buy petrol at old price as price is not updated yet and new price applies from tomorrow.&lt;/p&gt;

&lt;p&gt;CDN is another example. Platforms like Cloudflare continue serving cached content to users while fetching fresh content from the origin server in the background.&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AqLVG0dTJ46ZA7cbzoy1_VQ.png" 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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AqLVG0dTJ46ZA7cbzoy1_VQ.png" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stale-While-Revalidate works the same way. When a cache key expires, the system continues to serve old cached data and refreshes cache in background at the same time. Once the new data is ready, future requests get the updated cache.&lt;/p&gt;

&lt;p&gt;This ensures users never face a slow response because of cache expiry. The system stays responsive even during cache regeneration. No waiting. No database spike. No thundering herd.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cache Warming / Pre-Warming
&lt;/h3&gt;

&lt;p&gt;Before every IPL match, Hotstar engineers start preparing the servers for live streaming to millions of users. They load match data, player stats, team lineups, and streaming configurations into cache well before the first ball is bowled. Everything is already ready before users open the app.&lt;/p&gt;

&lt;p&gt;Netflix does this every night. They pre-compute the homepage for every user profile and load it into cache before you even open the app. By the time you login, your homepage is already ready.&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AGAHjqbZkmM46-qlSEQzSZg.png" 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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AGAHjqbZkmM46-qlSEQzSZg.png" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is called Cache Warming. Instead of waiting for the first request to hit the database and build the cache, the system proactively loads the cache before traffic arrives. This ensures the cache is already hot and ready to serve before users start coming in.&lt;/p&gt;

&lt;p&gt;Without cache warming, the first wave of users after a big event launch hits an empty cache. Database gets slammed. The system slows down. That is exactly the thundering herd situation we want to avoid. Cache warming ensures the herd never finds an empty cache.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tradeoffs
&lt;/h3&gt;

&lt;p&gt;Every caching strategy is a tradeoff between Freshness, Speed and Consistency. Freshness means how up-to-date your cached data is. Speed means how fast your system responds. Consistency means how uniform the data is across all users at the same time.&lt;/p&gt;

&lt;p&gt;If you want fresh and consistent data every time, your database may slow down under high traffic because you are not serving older data from cache. If you want to reduce latency and maintain consistency, caching helps but may not always serve the freshest data. If you want high consistency with reduced latency, you may need to serve slightly older data until the cache is updated.&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AGgsV-mU_HSx5JWqjqodjTA.png" 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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AGgsV-mU_HSx5JWqjqodjTA.png" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  When to Use Which Strategy
&lt;/h3&gt;

&lt;p&gt;There is no thumb rule for choosing a caching strategy. It totally depends on your use case, your traffic patterns, and how critical data freshness is for your system.&lt;/p&gt;

&lt;p&gt;Here is a simple guide to help you decide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If your system has many cache keys expiring around the same time, start with &lt;strong&gt;TTL Jitter&lt;/strong&gt;. It is the simplest fix and works well as a default for all distributed systems.&lt;/li&gt;
&lt;li&gt;If you have hot keys that are hit by millions of requests, use &lt;strong&gt;Probabilistic Early Re-computation&lt;/strong&gt;. It ensures cache is always ready before expiry hits.&lt;/li&gt;
&lt;li&gt;If rebuilding cache is expensive and you cannot afford duplicate recomputation, use &lt;strong&gt;Mutex / Cache Locking&lt;/strong&gt;. One request rebuilds, others wait.&lt;/li&gt;
&lt;li&gt;If your system is read-heavy and you can tolerate slightly old data, use &lt;strong&gt;Stale-While-Revalidate&lt;/strong&gt;. Speed is the priority here.&lt;/li&gt;
&lt;li&gt;If you know a traffic spike is coming, like an IPL match or a sale day, use &lt;strong&gt;Cache Warming&lt;/strong&gt;. Prepare before the herd arrives.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And remember, these strategies are not mutually exclusive. In real systems like Hotstar or Amazon, engineers often combine multiple strategies together. For example, TTL Jitter with Cache Warming before a big event, or Mutex with Stale-While-Revalidate for read-heavy APIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;After that failed exam, we made two important changes in our cache strategies. We started using multiple Cache TTL values and set them to expire at different times to avoid simultaneous expiry. We also pre-warmed our servers before every big event to ensure cache was ready before traffic arrived.&lt;/p&gt;

&lt;p&gt;These two changes made all the difference. We tested the system for 30,000 students and this time, everything worked smoothly.&lt;/p&gt;

&lt;p&gt;That experience taught me that caching is not just a performance tool. In distributed systems, how you manage cache can be the difference between a smooth experience and a total system failure.&lt;/p&gt;

&lt;p&gt;Start simple. Use TTL Jitter as your default. Add more strategies as your system grows. And always prepare before the spike hits, not after.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>distributedsystems</category>
      <category>performance</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>The Thundering Herd Problem</title>
      <dc:creator>Deepak Singh Solanki</dc:creator>
      <pubDate>Sun, 08 Mar 2026 17:06:53 +0000</pubDate>
      <link>https://dev.to/deepakinsights/the-thundering-herd-problem-j7b</link>
      <guid>https://dev.to/deepakinsights/the-thundering-herd-problem-j7b</guid>
      <description>&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AD5NYf2JmFC2Hli9fOMrWug.png" 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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AD5NYf2JmFC2Hli9fOMrWug.png" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Thundering Herd Problem
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;In 2021, I was working on an EdTech ERP system. COVID had pushed everything online, and all institutions were facing issues related to online education. We built this system and deployed it on the AWS cloud. We were using &lt;strong&gt;horizontal scaling&lt;/strong&gt; techniques to handle high traffic. We set up a &lt;strong&gt;load balancer&lt;/strong&gt; , Docker, &lt;strong&gt;auto scaling&lt;/strong&gt; , &lt;strong&gt;cache&lt;/strong&gt; to make sure that the server can handle high load.&lt;/p&gt;

&lt;p&gt;The client was expecting 10000 student logins, so we had done &lt;strong&gt;load testing&lt;/strong&gt; for 10000 users as asked by the client. After this testing, we decided to organise a mock test with real students on Sunday at 5 PM. We were ready.&lt;/p&gt;

&lt;p&gt;The exam started at 5 PM, and we got a traffic of 25000 students simultaneously. Still, everyone was cool as we had already set up the &lt;strong&gt;auto scaling&lt;/strong&gt; for the server. But we forgot one thing. &lt;strong&gt;Auto scaling&lt;/strong&gt; isn’t instant and the server scaling time can vary from seconds to minutes, and the server went down. After 5 minutes, the server was ready to handle this load, but another problem hit us. All the &lt;strong&gt;cache&lt;/strong&gt; expired simultaneously as the &lt;strong&gt;cache TTL&lt;/strong&gt; was set to expire between 5 PM to 6 PM every Sunday.&lt;/p&gt;

&lt;p&gt;So 25,000 students hit the system, and the &lt;strong&gt;cache&lt;/strong&gt; expired simultaneously, so all requests went straight to &lt;strong&gt;DB&lt;/strong&gt; , and &lt;strong&gt;DB&lt;/strong&gt; slowed everything. The exam hadn’t even started properly. We were frantically checking logs, and students were refreshing their screens.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Thundering Herd Problem
&lt;/h3&gt;

&lt;p&gt;Before going to the technical definition, we need to understand how a user reacts to online sale opening. Everyone is ready with their wishlists, fingers on the ‘Buy Now’ button, so websites face high traffic. But when the website starts slowing down, then the user continuously starts refreshing the page. So here is the situation: the website is slow because of high load and everyone refreshes the page to get faster response which increases the load even further and it may lead to system failure.&lt;/p&gt;

&lt;p&gt;This is exactly what happens inside your system too. When thousands of requests hit the system at the same time, the system can’t handle it. That’s the &lt;strong&gt;Thundering Herd Problem&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This problem commonly occurs in three places in your system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Load Balancer / Auto Scaling:&lt;/strong&gt; We use &lt;strong&gt;Load Balancer&lt;/strong&gt; to distribute the incoming traffic between all available servers. Let’s say if you set up three servers, then the load balancer will make sure that traffic can properly route to all servers without sending all traffic to any one of them.&lt;/p&gt;

&lt;p&gt;But when traffic suddenly spikes, then available servers are not able to handle all traffic. The system tries to scale by adding more servers. But &lt;strong&gt;auto scaling&lt;/strong&gt; isn’t instant. Those new servers take time to spin up: sometimes seconds, sometimes minutes. In that gap, your existing servers are taking all the hits alone.&lt;/p&gt;

&lt;p&gt;This is exactly what happened with us. 25,000 students hit the system, auto scaling triggered, but the server went down before new servers could join.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cache:&lt;/strong&gt;  &lt;strong&gt;Cache&lt;/strong&gt; is used to store frequently accessed data in high-speed memory (e.g., RAM) to reduce database load and improve &lt;strong&gt;latency&lt;/strong&gt;. It allows the system to access data faster. Each cache has a &lt;strong&gt;TTL&lt;/strong&gt; which tells about the time when cache expires and must be refreshed. When a cache expires, all the data requests directly hit the database.&lt;/p&gt;

&lt;p&gt;If the cache expires one by one at different times, the database can handle it easily. But if all the cache expires at the same time, all incoming requests find &lt;strong&gt;empty cache&lt;/strong&gt; and hit the database that spikes database load.&lt;/p&gt;

&lt;p&gt;That’s exactly what happened with us. Our &lt;strong&gt;cache TTL&lt;/strong&gt; was set to expire between 5 PM to 6 PM every Sunday, the same time our exam started.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Database:&lt;/strong&gt; A database contains a large amount of information, some data is frequently requested by clients. We already discussed that we use &lt;strong&gt;cache&lt;/strong&gt; to store frequently accessed data. When the cache is working properly, these requests never reach the database. Cache handles them directly. It keeps the database free for heavy or complex queries.&lt;/p&gt;

&lt;p&gt;But when cache is not available, all requests hit the &lt;strong&gt;database&lt;/strong&gt; directly, causing a sudden, massive spike in identical queries, leading to severe &lt;strong&gt;performance degradation&lt;/strong&gt; or total system slowdown/failure.&lt;/p&gt;

&lt;p&gt;This same thing happened with us on the exam day. &lt;strong&gt;Cache&lt;/strong&gt; expired simultaneously and all student requests hit the &lt;strong&gt;database&lt;/strong&gt; for the same exam data, which eventually slowed down the system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-world Example
&lt;/h3&gt;

&lt;p&gt;We already discussed how the &lt;strong&gt;Thundering Herd Problem&lt;/strong&gt; affected our mock exam. Now let’s look at some more real world examples that will help you understand this problem better:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Live Streaming:&lt;/strong&gt; On India vs Pak match day, billions of users are watching this match online. On these important match days, platforms receive months’ worth of traffic in a single day. So, their system must be ready to handle this &lt;strong&gt;simultaneous load&lt;/strong&gt; to prevent their system from getting down.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fantasy apps:&lt;/strong&gt; At the time of toss, millions of people are active on their fantasy apps to build their teams to win big rewards. This requires fantasy app servers to be ready to handle this &lt;strong&gt;simultaneous, high-volume traffic&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UPI / Payment Gateway:&lt;/strong&gt; Nowadays, everyone likes to pay digitally. These payment applications handle millions of transactions every second. This makes these systems vulnerable to going down. Any sudden &lt;strong&gt;traffic spike&lt;/strong&gt; can bring down these systems instantly. I am sure you have experienced this during peak hours, salary day or in festival season.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tax Filing:&lt;/strong&gt; We all need to file taxes to the government. Also, we need to submit this information online using government portals. Now think about the traffic, when everyone is trying to file their income tax / GST returns before the deadline. This &lt;strong&gt;high-volume traffic&lt;/strong&gt; slows down systems and sometimes brings it down for some time.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  How Traffic Spikes Overload Systems?
&lt;/h3&gt;

&lt;p&gt;Before discussing this, first we need to understand that all system components like &lt;strong&gt;CPU&lt;/strong&gt; , &lt;strong&gt;memory&lt;/strong&gt; , &lt;strong&gt;database&lt;/strong&gt; , &lt;strong&gt;disk&lt;/strong&gt; , &lt;strong&gt;bandwidth&lt;/strong&gt; have a limited capacity. It cannot be infinite. More resources definitely increase system capacity, but the system always reaches &lt;strong&gt;bottlenecks&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In a normal scenario, a system is designed to handle a fixed number of requests. When a request arrives, the server first checks the &lt;strong&gt;cache&lt;/strong&gt;. If the data exists in cache, it returns the response immediately. Otherwise, the request goes to the &lt;strong&gt;database&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When a sudden &lt;strong&gt;traffic spike&lt;/strong&gt; hits the server simultaneously, the system first tries to handle them with the available resources. The server also starts &lt;strong&gt;scaling&lt;/strong&gt; when necessary.&lt;/p&gt;

&lt;p&gt;Now if &lt;strong&gt;cache&lt;/strong&gt; expires during this high traffic, then all the requests start hitting the &lt;strong&gt;database&lt;/strong&gt; , which eventually overloads the &lt;strong&gt;connection pool&lt;/strong&gt; and query responses slow down because of excessive queries.&lt;/p&gt;

&lt;p&gt;During this time, users get delayed responses and sometimes it can lead to &lt;strong&gt;timeouts&lt;/strong&gt;. Clients start retrying because of failed or slow response. This leads to additional traffic to the system.&lt;/p&gt;

&lt;p&gt;This creates a dangerous cycle: more traffic, more retries, more load. It continues until the system slows down or crashes completely.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is it Dangerous in Distributed Systems?
&lt;/h3&gt;

&lt;p&gt;In a single server system, the &lt;strong&gt;Thundering Herd Problem&lt;/strong&gt; is bad. But in &lt;strong&gt;distributed systems&lt;/strong&gt; , it becomes truly dangerous.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;distributed systems&lt;/strong&gt; , multiple services depend on each other. When one service slows down, all dependent services start struggling too. &lt;strong&gt;Threads&lt;/strong&gt; get blocked, memory fills up, and &lt;strong&gt;connection pools&lt;/strong&gt; get exhausted. New requests find no available resources and start failing. This creates a chain reaction:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Failure → Retry → More Load → More Failure.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What started as a simple &lt;strong&gt;cache expiry&lt;/strong&gt; now spreads across every service in your architecture. A small &lt;strong&gt;synchronization issue&lt;/strong&gt; becomes a full system breakdown. This is why distributed systems must be designed assuming failures will happen and must be contained before they spread.&lt;/p&gt;

&lt;h3&gt;
  
  
  Normal Spike vs Thundering Herd
&lt;/h3&gt;

&lt;p&gt;Not every traffic spike is a &lt;strong&gt;Thundering Herd&lt;/strong&gt;. Here is the difference:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Normal spike:&lt;/strong&gt; When traffic spikes gradually, the system can predict this and manage it accordingly. It also provides a breathing window for the system for &lt;strong&gt;auto-scaling&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thundering Herd:&lt;/strong&gt; When high-volume &lt;strong&gt;traffic spike&lt;/strong&gt; hits the server simultaneously, the system struggles to handle the traffic. It forces the system to work at peak capacity and there is no breathing window for &lt;strong&gt;auto-scaling&lt;/strong&gt; that leads to total failure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Impact on System Components
&lt;/h3&gt;

&lt;p&gt;Let’s understand the impact of the &lt;strong&gt;Thundering Herd Problem&lt;/strong&gt; on different system components:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CPU:&lt;/strong&gt; When the herd hits, &lt;strong&gt;CPU utilization&lt;/strong&gt; spikes to 100%. The processor starts struggling with slow processing and high &lt;strong&gt;context switching&lt;/strong&gt; which increases response time and the system tries to scale by adding more resources, but by then, the damage is already done.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Database:&lt;/strong&gt; The &lt;strong&gt;database&lt;/strong&gt; starts receiving a high volume of identical queries simultaneously which exhausts all available connections. This leads to &lt;strong&gt;lock contention&lt;/strong&gt; and possible &lt;strong&gt;deadlocks&lt;/strong&gt;. Queries wait in a long queue, resulting in slow query responses and sometimes complete database failure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cache:&lt;/strong&gt; When the &lt;strong&gt;Thundering Herd&lt;/strong&gt; hits, thousands of requests miss the &lt;strong&gt;cache&lt;/strong&gt; at the same time and every one of them tries to regenerate the same data simultaneously. This creates massive CPU and network pressure on the cache server, causing &lt;strong&gt;memory spikes&lt;/strong&gt; and &lt;strong&gt;rapid eviction cycles&lt;/strong&gt;. Instead of protecting your database, your cache becomes part of the problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Load Balancer:&lt;/strong&gt; The &lt;strong&gt;load balancer&lt;/strong&gt; struggles to distribute requests evenly as servers become unresponsive or slow to reply.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Latency:&lt;/strong&gt; All of the above situations directly impact &lt;strong&gt;latency&lt;/strong&gt;. Slow cache, overloaded database, and exhausted CPU, everything adds delay to every single request. Users start seeing slow page loads, &lt;strong&gt;timeouts&lt;/strong&gt; , and failed requests. What normally takes milliseconds can take seconds. This is when users lose trust in your system.&lt;/p&gt;

&lt;p&gt;Each of these situations can contribute to a complete system breakdown.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prevention Techniques
&lt;/h3&gt;

&lt;p&gt;Once we understand its impact, now let’s look into the prevention techniques:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request Coalescing:&lt;/strong&gt; Remember the notice board in school? When the principal wants to inform everyone about the upcoming exam, he just publishes a notice, not informing each student individually. In system design, it’s called &lt;strong&gt;Request Coalescing&lt;/strong&gt;. Only the first request hits the database and all other requests wait. Once the response is ready, it’s shared with all. It’s simple, but not effective for &lt;strong&gt;distributed systems&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cache Locking / Mutex:&lt;/strong&gt; Think about the biometric machine in your office. When your colleague is punching attendance, others wait till it’s done. &lt;strong&gt;Cache Locking&lt;/strong&gt; works in the same way. When &lt;strong&gt;cache&lt;/strong&gt; expires, only the first request acquires the &lt;strong&gt;lock&lt;/strong&gt; and hits the database to regenerate the cache. All other requests wait till the cache is ready. The lock is released and all waiting requests get the data directly from the cache. It’s important to always set the expiry on the lock. If the request that acquired the lock crashes, the lock must &lt;strong&gt;auto-release&lt;/strong&gt;. Otherwise, all waiting requests will be stuck forever.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stale-While-Invalidate:&lt;/strong&gt; Got the salary credited message, but banking app showing the old balance. Wondering what happened? It’s not a system issue, balance updating in background. Correct balance shows after some time. Banks use this technique to ensure a smooth experience. In system design, this is called &lt;strong&gt;Stale-While-Invalidate&lt;/strong&gt;. It ensures all the requests continue to get the data without hitting the database. &lt;strong&gt;Cache&lt;/strong&gt; is updating in background, once the &lt;strong&gt;cache refresh&lt;/strong&gt; completes, new cache serves future requests. This approach reduces &lt;strong&gt;latency&lt;/strong&gt; , prevents spikes on the backend, and ensures smooth traffic even during cache regeneration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Staggered Expiry:&lt;/strong&gt; Different roads get green signal at different times to avoid all traffic moving simultaneously. If all roads get green signal at once, then it can result in a mess. Similarly expiring all cache at once triggers a &lt;strong&gt;Thundering Herd&lt;/strong&gt;. In the &lt;strong&gt;Staggered Expiry&lt;/strong&gt; technique, the system uses expiry &lt;strong&gt;TTL&lt;/strong&gt; with a random factor for all cache keys. It ensures all cache keys don’t expire at once and keeps the database safe from simultaneous queries. It reduces spikes in load and helps maintain system stability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exponential Backoff:&lt;/strong&gt; You purchase an iPhone and try to make a payment. But the bank server is down. You wait for a minute, before retrying. If it still does not work, then you wait for a few minutes before retry. This small random delay gives the server time to recover. The same technique is known as &lt;strong&gt;Exponential Backoff&lt;/strong&gt; in system design. This technique is used to limit the number of &lt;strong&gt;retries&lt;/strong&gt; when a server is under the load. Instead of retrying immediately after a failed request, each subsequent retry doubles the delay by an exponentially increasing interval. A small random &lt;strong&gt;jitter&lt;/strong&gt; is also added to each retry to avoid all clients retrying at the exact same time. Without this, all failed requests retry simultaneously that add more load on an already struggling server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rate Limiting:&lt;/strong&gt; We all have experienced OTP delays on websites. Sometimes, we need to wait before requesting another OTP. That’s &lt;strong&gt;Rate Limiting&lt;/strong&gt; in action. In system design, &lt;strong&gt;Rate Limiting&lt;/strong&gt; controls the number of incoming requests to prevent system overload. During a thundering herd, it acts as the first line of defence. It blocks excessive requests before they reach the database. Because it’s always better to reject some requests than to crash the entire system.&lt;/p&gt;

&lt;h3&gt;
  
  
  What We Did to Fix It
&lt;/h3&gt;

&lt;p&gt;After the failed exam, we decided to analyse our system design and list all the bottlenecks. After checking this carefully, we identified the issue and started working on solutions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First we decided to &lt;strong&gt;pre-warm&lt;/strong&gt; our servers, before any big event for at least 2x the expected load, which ensures that the server is ready to handle requests from high-volume traffic. Also, reconfigured &lt;strong&gt;auto scaling&lt;/strong&gt; triggers to 70%, which was previously set as 90%.&lt;/li&gt;
&lt;li&gt;We decided to use multiple &lt;strong&gt;Cache TTL&lt;/strong&gt; and set it to expire at midnight to avoid such situations again.&lt;/li&gt;
&lt;li&gt;We also worked on our &lt;strong&gt;indexing&lt;/strong&gt; and &lt;strong&gt;cache optimization&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;After completing these changes, we tested the server for 1 lakh users, recorded its results and built a flow chart to handle these situations better in future.&lt;/li&gt;
&lt;li&gt;Finally, we set up Slack/email &lt;strong&gt;alerts&lt;/strong&gt; , so team members can get alerts before things get worse.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Things take time. But, this time we were ready. Next Sunday, we conducted a successful exam for 30,000 students.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;A Sunday in 2021 taught me some important lessons about system design and gave me a challenge to solve it. I took this challenge and solved it and you also can solve this just by knowing the bottlenecks in your system. Things that I learned on that evening are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Thundering Herd&lt;/strong&gt; is not just a traffic problem, it’s a &lt;strong&gt;synchronization problem&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Every system has a breaking point, we just need to know before it happens.&lt;/li&gt;
&lt;li&gt;Sometimes small misconfigurations (like a wrong &lt;strong&gt;TTL&lt;/strong&gt; ) can bring down entire systems.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, what we need to consider while designing a system:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Always test the system with its &lt;strong&gt;peak limits&lt;/strong&gt; , which tell you about system breakpoints.&lt;/li&gt;
&lt;li&gt;Always track traffic to understand system load.&lt;/li&gt;
&lt;li&gt;Using a proper &lt;strong&gt;cache TTL&lt;/strong&gt; can save your system from going down.&lt;/li&gt;
&lt;li&gt;Before any big event, check if &lt;strong&gt;server pre-warming&lt;/strong&gt; is required. Don’t wait for the herd to arrive.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The herd will come. The question is: will your system be ready?&lt;/p&gt;

</description>
      <category>thunderingherdproble</category>
      <category>systemdesignintervie</category>
      <category>systemdesignconcepts</category>
    </item>
  </channel>
</rss>
