<?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: Mohammad Zbib</title>
    <description>The latest articles on DEV Community by Mohammad Zbib (@mhmd_zbib).</description>
    <link>https://dev.to/mhmd_zbib</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%2F2576006%2Fae31333f-a8a3-4288-befc-39909b3d94fd.jpg</url>
      <title>DEV Community: Mohammad Zbib</title>
      <link>https://dev.to/mhmd_zbib</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mhmd_zbib"/>
    <language>en</language>
    <item>
      <title>MongoDB at Scale: Common Anti Patterns That Silently Kill Performance</title>
      <dc:creator>Mohammad Zbib</dc:creator>
      <pubDate>Wed, 18 Feb 2026 15:41:18 +0000</pubDate>
      <link>https://dev.to/mhmd_zbib/mongodb-at-scale-common-anti-patterns-that-silently-kill-performance-jci</link>
      <guid>https://dev.to/mhmd_zbib/mongodb-at-scale-common-anti-patterns-that-silently-kill-performance-jci</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Is your MongoDB app running slow? The problem might not be your code, but how your database is set up. MongoDB is very flexible, but this can sometimes lead to big performance issues if you don't use it right. This article will explain common MongoDB problems and give you smart ways to fix them, so your apps can be fast and handle a lot of users.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Good and Bad of MongoDB's Flexibility
&lt;/h2&gt;

&lt;p&gt;MongoDB lets you build apps quickly because its data structure is easy to change. But this freedom can also hide problems. If you treat MongoDB like a traditional SQL database, you'll run into issues like making too many small requests (N+1 queries), scanning huge amounts of data, and using complicated data processing steps that slow everything down. To truly master MongoDB, you need to understand how it works inside and design your data and queries to match its strengths.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Performance Problems and How to Solve Them
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. The N+1 Query Problem: A Hidden Performance Killer
&lt;/h3&gt;

&lt;p&gt;The N+1 query problem happens when your app first gets a list of main items, and then for &lt;em&gt;each&lt;/em&gt; of those items, it makes a separate request to get related details (the "N" queries). This means your app talks to the database too much, which wastes time and makes the database work harder.&lt;/p&gt;

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

&lt;p&gt;Imagine you have &lt;code&gt;orders&lt;/code&gt; and &lt;code&gt;customers&lt;/code&gt; collections. To show a list of orders with customer names, a common mistake is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 1. Get all orders (the "+1" query)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;orders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;orders&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toArray&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// 2. For each order, get its customer (the "N" queries)&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;customers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customerId&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have 100 orders, this runs 101 queries. Each of those 100 customer queries might have to scan through the whole &lt;code&gt;customers&lt;/code&gt; collection if you don't have the right index, making things even slower.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Smart Solutions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keep Related Data Together (Embedding):&lt;/strong&gt; If data is often used together and doesn't change much, put it directly inside the main document. For example, put the customer's name and key details right into the &lt;code&gt;order&lt;/code&gt; document. This means you only need one request to get all the info.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batching Requests:&lt;/strong&gt; If you can't embed data, gather all the IDs you need and ask for them in one go. Instead of 100 separate requests for customers, make one request asking for all 100 customer IDs at once. This saves a lot of back-and-forth communication.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. The High Cost of Scanning Millions of Documents
&lt;/h3&gt;

&lt;p&gt;When MongoDB can't use an index to find data, it has to read every single document in a collection. This is called a &lt;code&gt;COLLSCAN&lt;/code&gt; (collection scan). If your collection has millions of documents, reading all of them takes a very long time, uses a lot of your computer's power, and makes your app feel very slow. In systems with many servers (sharded clusters), this problem gets even worse because it has to scan across all of them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Smart Solutions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Good Indexing Strategy:&lt;/strong&gt; Indexes are like a book's table of contents. They help MongoDB find data quickly. Create indexes on all fields you search by, sort by, or use in &lt;code&gt;$lookup&lt;/code&gt; operations. For searches that use multiple fields, create &lt;strong&gt;compound indexes&lt;/strong&gt; (indexes on several fields). Also, try to make &lt;strong&gt;covered queries&lt;/strong&gt;, where all the data needed for a query is found directly in the index, so MongoDB doesn't even need to look at the main documents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choose Fields Carefully for Indexes:&lt;/strong&gt; Put indexes on fields that have many different values (high cardinality) and are good at narrowing down search results. Avoid indexing fields with only a few different values unless they are part of a compound index that helps a lot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Partial Indexes:&lt;/strong&gt; If only some of your documents have a certain field, or if you only care about a specific group of documents, you can use &lt;strong&gt;partial indexes&lt;/strong&gt;. These indexes are smaller and faster because they only cover a part of your collection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TTL Indexes:&lt;/strong&gt; For data that expires (like old logs), &lt;strong&gt;TTL indexes&lt;/strong&gt; automatically delete old documents. This keeps your collections from getting too big and helps queries stay fast.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use &lt;code&gt;explain()&lt;/code&gt; to See What's Happening:&lt;/strong&gt; Use &lt;code&gt;db.collection.explain("executionStats")&lt;/code&gt; to understand how your queries are running. Look for &lt;code&gt;COLLSCAN&lt;/code&gt; (bad!), and check &lt;code&gt;totalKeysExamined&lt;/code&gt; (how many index entries it looked at) versus &lt;code&gt;totalDocsExamined&lt;/code&gt; (how many documents it looked at). If &lt;code&gt;totalDocsExamined&lt;/code&gt; is much higher than the number of results you get, your index isn't working well.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. The &lt;code&gt;$lookup&lt;/code&gt; (Join) Cost: A Tricky Balance
&lt;/h3&gt;

&lt;p&gt;MongoDB's &lt;code&gt;$lookup&lt;/code&gt; feature lets you combine data from different collections, similar to a &lt;code&gt;JOIN&lt;/code&gt; in SQL. It's powerful, but it's not a magic bullet. Each &lt;code&gt;$lookup&lt;/code&gt; step uses up resources and can slow things down, especially with large amounts of data or if you don't have the right indexes. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Smart Solutions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Index the Joined Fields:&lt;/strong&gt; Always make sure the fields you use to connect collections in &lt;code&gt;$lookup&lt;/code&gt; (the &lt;code&gt;localField&lt;/code&gt; and &lt;code&gt;foreignField&lt;/code&gt;) have indexes. This helps MongoDB find matching documents quickly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use &lt;code&gt;$lookup&lt;/code&gt; Less Often:&lt;/strong&gt; Don't use &lt;code&gt;$lookup&lt;/code&gt; for every connection between data. If you often need related data together, embedding it is usually better. Use &lt;code&gt;$lookup&lt;/code&gt; only when embedding isn't practical, like for very large related data or complex many-to-many relationships.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watch Memory Use:&lt;/strong&gt; &lt;code&gt;$lookup&lt;/code&gt; operations can use a lot of memory. If they use too much, MongoDB might have to write temporary data to disk, which is very slow. Keep an eye on memory usage and consider changing &lt;code&gt;aggregationMemoryLimitMb&lt;/code&gt; if needed, or simplify your query.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. The Aggregation Pipeline Trap: Powerful but Dangerous
&lt;/h3&gt;

&lt;p&gt;MongoDB's aggregation framework is great for complex data tasks. But if you build long, complicated pipelines (sequences of operations), they can become very slow. Each step in the pipeline processes the results of the previous one, so one slow step early on can make the whole pipeline crawl.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Smart Solutions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Avoid large aggregation pipelines:&lt;/strong&gt; MongoDB is not a relational database. Complex pipelines with numerous &lt;code&gt;$lookup&lt;/code&gt; stages significantly degrade performance. Instead, execute multiple small, focused queries with minimal lookups, and perform data composition at the application/server layer. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep Pipelines Simple:&lt;/strong&gt; Avoid making pipelines too long or complex. Break down big tasks into smaller ones, or do some of the data processing in your application code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Order Steps Smartly:&lt;/strong&gt; The order of steps in your pipeline matters a lot. Always use &lt;code&gt;$match&lt;/code&gt; (filter) and &lt;code&gt;$project&lt;/code&gt; (choose specific fields) early. This reduces the amount of data that later, more expensive steps have to process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;$unwind&lt;/code&gt; with Caution:&lt;/strong&gt; The &lt;code&gt;$unwind&lt;/code&gt; step creates a separate document for each item in an array. If your arrays are very large, this can create a huge number of documents, using up a lot of memory and slowing things down. Look for other ways to handle arrays if &lt;code&gt;$unwind&lt;/code&gt; is too slow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Index for &lt;code&gt;$group&lt;/code&gt;:&lt;/strong&gt; If you use &lt;code&gt;$group&lt;/code&gt; to combine documents, make sure the field you're grouping by (&lt;code&gt;_id&lt;/code&gt;) is indexed. This helps MongoDB group documents efficiently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watch Memory (Again):&lt;/strong&gt; Many aggregation steps can use a lot of memory and spill to disk. Use &lt;code&gt;explain()&lt;/code&gt; to check how much memory and disk space your pipelines are using. For very large tasks, consider doing some processing outside of MongoDB, like with Apache Spark.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to Keep MongoDB Fast
&lt;/h2&gt;

&lt;p&gt;Making MongoDB fast for big applications is an ongoing effort. It means always thinking about how you design your data, how you use indexes, and how you write your queries. You need to constantly check how your database is performing and make changes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Always Check for Slow Queries:&lt;/strong&gt; Turn on the database profiler (&lt;code&gt;db.setProfilingLevel(1)&lt;/code&gt;) to find queries that are taking too long. Look at the results to see which queries are run often, take a long time, or look at too many documents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor Your Database:&lt;/strong&gt; Use tools like MongoDB Cloud Manager or Ops Manager to watch important numbers like how many operations are happening, memory use, CPU use, and how fast data is copied between servers. Pay attention to how much data is being read from and written to disk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sharding for Huge Data:&lt;/strong&gt; For extremely large amounts of data, you need to split it across many servers (sharding). But choosing the wrong way to split your data can create problems like some servers being overloaded while others are idle. Pick a sharding key that spreads data evenly and works well with your common queries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tune Your Hardware:&lt;/strong&gt; Make sure your servers have enough CPU, RAM, and fast storage (SSDs). Also, adjust MongoDB settings (like &lt;code&gt;wiredTigerCacheSizeGB&lt;/code&gt;) to match how your app uses the database.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  In Short
&lt;/h2&gt;

&lt;p&gt;To make MongoDB perform well at an advanced level, you need to deeply understand how it works. It's about smart data design, careful indexing, and writing efficient queries. By avoiding common mistakes and using these advanced tips, you can build strong, fast, and scalable applications that handle heavy use with ease.&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>database</category>
      <category>backend</category>
    </item>
    <item>
      <title>Building Real Time Systems That Actually Scale</title>
      <dc:creator>Mohammad Zbib</dc:creator>
      <pubDate>Sat, 30 Aug 2025 15:23:02 +0000</pubDate>
      <link>https://dev.to/mhmd_zbib/building-real-time-systems-that-actually-scale-om6</link>
      <guid>https://dev.to/mhmd_zbib/building-real-time-systems-that-actually-scale-om6</guid>
      <description>&lt;p&gt;There’s something magical about building apps that feel alive. When a message appears instantly in a chat. When notifications pop up the moment something happens. When multiple people can edit the same document together without friction. That’s the power of real time applications.&lt;/p&gt;

&lt;p&gt;But behind the magic is a story of architecture. A journey where each step solves one problem, but often creates the next. Let’s walk through that journey, from the simplest setups to production ready systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  The beauty of Starting Simple
&lt;/h3&gt;

&lt;p&gt;Let's start where most of us do, putting everything in one place.&lt;br&gt;
Your app handles WebSocket connections, processes business logic,&lt;br&gt;
talks to the database, and sends real time updates all from the same&lt;br&gt;
server. It's like having one super capable person running your&lt;br&gt;
entire operation.&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%2F5m3d0mmhsmetyzwgcf62.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%2F5m3d0mmhsmetyzwgcf62.png" alt=" " width="800" height="183"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And honestly, this setup works well at the start.Deployment is simple. Debugging is easier since everything lives in one place. Fast Real time updates as there’s no extra network hop. For early users, it feels almost magical.&lt;/p&gt;

&lt;h3&gt;
  
  
  When Your Success Becomes Your Problem
&lt;/h3&gt;

&lt;p&gt;Success brings more users. And more users, means your single server starts juggling a lot more balls. Each WebSocket connection needs memory and processing power. Your database queries take longer. Background tasks compete for attention.&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%2F5mvqzw3ymhqq9xbrn4o3.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%2F5mvqzw3ymhqq9xbrn4o3.png" alt=" " width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Suddenly, everything starts slowing down together. When you need to&lt;br&gt;
deploy a small bug fix, all your users get disconnected. When your&lt;br&gt;
database gets busy, your real time updates lag. It's like having one&lt;br&gt;
person trying to answer phones, cook meals, and greet customers all&lt;br&gt;
at once.&lt;/p&gt;

&lt;h3&gt;
  
  
  Breaking Things Apart: Microservices
&lt;/h3&gt;

&lt;p&gt;Breaking things apart solves these problems. Scaling one giant server is expensive and wasteful, need more payment processing power? You have to scale everything, even parts that don't need it. Plus, deploying a tiny notification fix kicks off every user.&lt;/p&gt;

&lt;p&gt;The natural next step is breaking things apart. Each microservice&lt;br&gt;
gets its own responsibility, user management, payments,&lt;br&gt;
notifications and each one handles its own WebSocket connections&lt;br&gt;
too. When something happens, services broadcast events to each other&lt;br&gt;
using a message system like RabbitMQ.&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%2Fe3iwabbtfhc4haty95be.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%2Fe3iwabbtfhc4haty95be.png" alt=" " width="800" height="271"&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%2Fxz7oyconeb708t4kyhjc.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%2Fxz7oyconeb708t4kyhjc.png" alt=" " width="800" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This feels cleaner. Services can scale independently,&lt;br&gt;
deployments don't kill everything, and your code is cleaner with&lt;br&gt;
each service focused on its specific job. RabbitMQ makes sure all&lt;br&gt;
services stay in sync, and you can add more instances when you need&lt;br&gt;
them.&lt;/p&gt;

&lt;h3&gt;
  
  
  The WebSocket Headache
&lt;/h3&gt;

&lt;p&gt;But wait now you have a different challenge. Microservices come with trafdeoffs, with 5 services and 3 instances each, you suddenly have 15 WebSocket servers running. That's a lot of overhead for something that used to be simple. Plus, scaling becomes tricky when you need more instances just to handle WebSocket connections, not business logic.&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%2Fyq82svcxfwphps77b9cu.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%2Fyq82svcxfwphps77b9cu.png" alt=" " width="800" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And let's talk about your frontend team, they're not happy. Now&lt;br&gt;
they need to manage multiple WebSocket connections, figure out which&lt;br&gt;
service to connect to for what data, and handle all the complexity&lt;br&gt;
that brings.&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%2F7x9wckiwrth864lav9wp.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%2F7x9wckiwrth864lav9wp.png" alt=" " width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  One Gateway to Rule Them All
&lt;/h3&gt;

&lt;p&gt;Here's where the socket gateway pattern comes in place. Instead of each service managing its own WebSocket connections, you create one dedicated service just for real time communication. Think of it as a&lt;br&gt;
specialized receptionist who knows exactly where to route every&lt;br&gt;
message.&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%2Fq5gp827wqh16vs5ntnqv.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%2Fq5gp827wqh16vs5ntnqv.png" alt=" " width="800" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your frontend connects to just one place, making development much&lt;br&gt;
simpler. The gateway listens for events from all your services and&lt;br&gt;
delivers them to the right users. Meanwhile, your business services&lt;br&gt;
can focus on what they do best, without worrying about WebSocket&lt;br&gt;
management.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Empty Room Problem
&lt;/h3&gt;

&lt;p&gt;Multiple gateway instances got a problem. When a service broadcasts an event, every gateway instance receives it even&lt;br&gt;
if most of them don't have the target users connected. It's like&lt;br&gt;
shouting an announcement in every room of a building, even when the&lt;br&gt;
person you're looking for is only in one room.&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%2Fpncp8o8ac1udmgtgtgua.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%2Fpncp8o8ac1udmgtgtgua.png" alt=" " width="800" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Imagine sending a notification to 1,000 users across 10 gateway&lt;br&gt;
instances. Each instance has to check if it has those users&lt;br&gt;
connected, resulting in 10,000 lookups where most come back empty.&lt;br&gt;
Your system spends more time looking for users it doesn't have than&lt;br&gt;
delivering messages to users it does have.&lt;/p&gt;

&lt;h3&gt;
  
  
  Smart Routing with Redis
&lt;/h3&gt;

&lt;p&gt;The solution is simple and elegant. Each gateway registers its connected users in Redis, creating a shared directory of who’s where. When a service needs to send an update, it looks up the user in Redis and sends the event directly to the right gateway. No guessing, no broadcasting.&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%2Ff2g85s35h0knq354n2s0.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%2Ff2g85s35h0knq354n2s0.png" alt=" " width="800" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Connections are dynamic, but Redis keeps everything up to date. Users can move between instances, gateways can scale out, and messages always find their destination. With optional optimizations like pub/sub and TTLs, the system stays fast, precise, and scalable.&lt;/p&gt;




&lt;p&gt;Scaling real time systems always brings new challenges. How do you keep messages fast and reliable as users and regions grow? If you have any suggestions, tips, or ideas, I’d love to hear from you, connect with me on &lt;a href="https://www.linkedin.com/in/mhmd-zbib/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>softwareengineering</category>
      <category>microservices</category>
      <category>distributedsystems</category>
      <category>backend</category>
    </item>
  </channel>
</rss>
