<?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: Derek mwale</title>
    <description>The latest articles on DEV Community by Derek mwale (@derekmwale).</description>
    <link>https://dev.to/derekmwale</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4042380%2F32f29659-b869-4e9b-914c-1584bd72f208.png</url>
      <title>DEV Community: Derek mwale</title>
      <link>https://dev.to/derekmwale</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/derekmwale"/>
    <language>en</language>
    <item>
      <title>Building a URL Shortener Like a Systems Engineer</title>
      <dc:creator>Derek mwale</dc:creator>
      <pubDate>Wed, 22 Jul 2026 17:01:32 +0000</pubDate>
      <link>https://dev.to/derekmwale/building-a-url-shortener-like-a-systems-engineer-5b63</link>
      <guid>https://dev.to/derekmwale/building-a-url-shortener-like-a-systems-engineer-5b63</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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frnvfbl3k25zk48lveq9u.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frnvfbl3k25zk48lveq9u.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A URL shortener looks like one of the simplest applications you can build.&lt;/p&gt;

&lt;p&gt;You paste a long URL.&lt;/p&gt;

&lt;p&gt;You get a short link.&lt;/p&gt;

&lt;p&gt;Someone clicks it.&lt;/p&gt;

&lt;p&gt;They are redirected.&lt;/p&gt;

&lt;p&gt;Done.&lt;/p&gt;

&lt;p&gt;At least that's how it looks from the outside.&lt;/p&gt;

&lt;p&gt;But behind a service like Bitly, TinyURL, or any large-scale link platform is a fascinating systems engineering problem.&lt;/p&gt;

&lt;p&gt;A production URL shortener needs to answer questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How do we generate unique short URLs?&lt;/li&gt;
&lt;li&gt;How do we handle billions of redirects?&lt;/li&gt;
&lt;li&gt;How do we make redirects extremely fast?&lt;/li&gt;
&lt;li&gt;How do we prevent abuse?&lt;/li&gt;
&lt;li&gt;How do we track analytics?&lt;/li&gt;
&lt;li&gt;How do we scale without everything breaking?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The interesting part is not writing the first version.&lt;/p&gt;

&lt;p&gt;The interesting part is designing something that survives growth.&lt;/p&gt;

&lt;p&gt;Let's build one like a systems engineer.&lt;/p&gt;




&lt;h1&gt;
  
  
  Understanding the Core Problem
&lt;/h1&gt;

&lt;p&gt;At the surface, the system does two things:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Create a Short URL
&lt;/h2&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://www.example.com/products/software-development-course
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://short.ly/a7Kx92
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. Redirect Users
&lt;/h2&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://short.ly/a7Kx92
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://www.example.com/products/software-development-course
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second operation is much more important.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because creating links happens occasionally.&lt;/p&gt;

&lt;p&gt;Redirects happen constantly.&lt;/p&gt;

&lt;p&gt;A popular link might receive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Thousands of clicks per second&lt;/li&gt;
&lt;li&gt;Millions of clicks per day&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The system should be optimized for reading, not writing.&lt;/p&gt;




&lt;h1&gt;
  
  
  High-Level Architecture
&lt;/h1&gt;

&lt;p&gt;A simple architecture might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                User
                 |
                 |
                 ▼

          API Gateway

                 |
        -----------------
        |               |
        ▼               ▼

 URL Service       Redirect Service

        |               |
        ▼               ▼

   Database          Cache

                         |
                         ▼

                    Analytics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each component has a clear responsibility.&lt;/p&gt;

&lt;p&gt;The URL service creates links.&lt;/p&gt;

&lt;p&gt;The redirect service handles traffic.&lt;/p&gt;

&lt;p&gt;The cache keeps popular links fast.&lt;/p&gt;

&lt;p&gt;Analytics collects information without slowing redirects.&lt;/p&gt;




&lt;h1&gt;
  
  
  Designing the Database
&lt;/h1&gt;

&lt;p&gt;At the core, we need to store the relationship:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;short_code → original_url
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A simple table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;BIGINT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;short_code&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;original_url&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;expires_at&lt;/span&gt; &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;short_code&lt;/th&gt;
&lt;th&gt;original_url&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;a7Kx92&lt;/td&gt;
&lt;td&gt;&lt;a href="https://example.com/article" rel="noopener noreferrer"&gt;https://example.com/article&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;b8Lm21&lt;/td&gt;
&lt;td&gt;&lt;a href="https://store.com/product" rel="noopener noreferrer"&gt;https://store.com/product&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The database answers one important question:&lt;/p&gt;

&lt;p&gt;"Where should this short code send the user?"&lt;/p&gt;




&lt;h1&gt;
  
  
  The Challenge: Generating Short Codes
&lt;/h1&gt;

&lt;p&gt;The biggest design decision is creating the short identifier.&lt;/p&gt;

&lt;p&gt;We need something:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Short&lt;/li&gt;
&lt;li&gt;Unique&lt;/li&gt;
&lt;li&gt;Fast to generate&lt;/li&gt;
&lt;li&gt;Collision resistant&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A common approach is Base62 encoding.&lt;/p&gt;

&lt;p&gt;Base62 uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a-z
A-Z
0-9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's 62 characters.&lt;/p&gt;

&lt;p&gt;A code like:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;62^6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;possible combinations.&lt;/p&gt;

&lt;p&gt;That gives billions of unique URLs.&lt;/p&gt;




&lt;h1&gt;
  
  
  Generating IDs
&lt;/h1&gt;

&lt;p&gt;One approach:&lt;/p&gt;

&lt;p&gt;Create a unique numeric ID.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Database ID:

123456
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;123456 → Base62

→

a7Kx92
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;New URL

    |

Generate ID

    |

Convert ID

    |

Store mapping

    |

Return short URL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple.&lt;/p&gt;

&lt;p&gt;Reliable.&lt;/p&gt;

&lt;p&gt;Fast.&lt;/p&gt;




&lt;h1&gt;
  
  
  Redirects Are the Critical Path
&lt;/h1&gt;

&lt;p&gt;When someone clicks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;short.ly/a7Kx92
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we need the fastest possible response.&lt;/p&gt;

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

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

   |

Extract code

   |

Check Cache

   |

Database Lookup

   |

Redirect User
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first place we look should be memory.&lt;/p&gt;




&lt;h1&gt;
  
  
  Adding Redis Cache
&lt;/h1&gt;

&lt;p&gt;Most URLs are not equally popular.&lt;/p&gt;

&lt;p&gt;A few links receive most traffic.&lt;/p&gt;

&lt;p&gt;This is called a:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Long Tail Distribution&lt;/strong&gt;&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Popular Link

████████████████████

Normal Links

██

Rare Links

█
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of hitting the database every time:&lt;br&gt;
&lt;/p&gt;

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

 |

Redis

 |

Database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first request loads the URL.&lt;/p&gt;

&lt;p&gt;Future requests are served instantly.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a7Kx92 → https://example.com/article
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;stored in Redis.&lt;/p&gt;

&lt;p&gt;Now redirects happen in milliseconds.&lt;/p&gt;




&lt;h1&gt;
  
  
  Handling Billions of URLs
&lt;/h1&gt;

&lt;p&gt;A small database works at first.&lt;/p&gt;

&lt;p&gt;But eventually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10 million URLs

100 million URLs

10 billion URLs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;becomes a different problem.&lt;/p&gt;

&lt;p&gt;We need strategies.&lt;/p&gt;




&lt;h1&gt;
  
  
  Database Sharding
&lt;/h1&gt;

&lt;p&gt;Instead of one huge database:&lt;br&gt;
&lt;/p&gt;

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

   |

----------------

Shard 1

Shard 2

Shard 3

Shard 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;URLs are distributed.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hash(short_code) % number_of_shards
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;determines where data lives.&lt;/p&gt;

&lt;p&gt;Now traffic is spread across multiple machines.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Importance of Read Optimization
&lt;/h1&gt;

&lt;p&gt;A URL shortener is a read-heavy system.&lt;/p&gt;

&lt;p&gt;Think about the ratio:&lt;/p&gt;

&lt;p&gt;Creating URLs:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Clicking URLs:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This changes our design priorities.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Caching&lt;/li&gt;
&lt;li&gt;Database indexes&lt;/li&gt;
&lt;li&gt;Low latency&lt;/li&gt;
&lt;li&gt;Fast lookups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not complicated write systems.&lt;/p&gt;




&lt;h1&gt;
  
  
  Adding Analytics
&lt;/h1&gt;

&lt;p&gt;Users want to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How many people clicked?&lt;/li&gt;
&lt;li&gt;Where did they come from?&lt;/li&gt;
&lt;li&gt;What devices did they use?&lt;/li&gt;
&lt;li&gt;Which countries clicked?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The mistake would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User clicks

   |

Save analytics

   |

Redirect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now analytics slows everything down.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User clicks

   |

Redirect immediately

   |

Send event asynchronously

   |

Process analytics later
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Message queues&lt;/li&gt;
&lt;li&gt;Event streams&lt;/li&gt;
&lt;li&gt;Background workers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;keeps the redirect fast.&lt;/p&gt;




&lt;h1&gt;
  
  
  Preventing Abuse
&lt;/h1&gt;

&lt;p&gt;A URL shortener can easily become an abuse platform.&lt;/p&gt;

&lt;p&gt;Attackers may use it for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Phishing&lt;/li&gt;
&lt;li&gt;Spam&lt;/li&gt;
&lt;li&gt;Malware distribution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A production system needs:&lt;/p&gt;

&lt;h2&gt;
  
  
  Rate Limiting
&lt;/h2&gt;

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

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

100 requests/minute

Allowed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





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

10,000 requests/minute

Blocked
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  URL Scanning
&lt;/h2&gt;

&lt;p&gt;Before creating a link:&lt;/p&gt;

&lt;p&gt;Check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Known malicious domains&lt;/li&gt;
&lt;li&gt;Suspicious patterns&lt;/li&gt;
&lt;li&gt;Malware databases&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Expiration
&lt;/h2&gt;

&lt;p&gt;Some links should not live forever.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Temporary campaign link

Expires after 30 days
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Handling Failures
&lt;/h1&gt;

&lt;p&gt;Distributed systems fail.&lt;/p&gt;

&lt;p&gt;Servers crash.&lt;/p&gt;

&lt;p&gt;Networks disconnect.&lt;/p&gt;

&lt;p&gt;Databases become unavailable.&lt;/p&gt;

&lt;p&gt;Design for failure.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Database Failure
&lt;/h2&gt;

&lt;p&gt;Use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replication&lt;/li&gt;
&lt;li&gt;Backups&lt;/li&gt;
&lt;li&gt;Failover systems&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Cache Failure
&lt;/h2&gt;

&lt;p&gt;The system should still work:&lt;br&gt;
&lt;/p&gt;

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

   X

Database

   ✓
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The cache improves speed.&lt;/p&gt;

&lt;p&gt;It should never be the only source of truth.&lt;/p&gt;




&lt;h1&gt;
  
  
  API Design
&lt;/h1&gt;

&lt;p&gt;A simple API:&lt;/p&gt;

&lt;h2&gt;
  
  
  Create Short URL
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /api/urls
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/article"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"short_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://short.ly/a7Kx92"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Redirect
&lt;/h2&gt;



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

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP 301 Redirect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://example.com/article
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  The Technologies I Would Choose
&lt;/h1&gt;

&lt;p&gt;A practical stack:&lt;/p&gt;

&lt;h2&gt;
  
  
  Backend
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Go&lt;/li&gt;
&lt;li&gt;Rust&lt;/li&gt;
&lt;li&gt;Java&lt;/li&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Database
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;MySQL&lt;/li&gt;
&lt;li&gt;DynamoDB&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cache
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Redis&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Queue
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;RabbitMQ&lt;/li&gt;
&lt;li&gt;Kafka&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Infrastructure
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Kubernetes&lt;/li&gt;
&lt;li&gt;Cloud Load Balancer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The technology matters less than the architecture.&lt;/p&gt;




&lt;h1&gt;
  
  
  What This Project Teaches
&lt;/h1&gt;

&lt;p&gt;A URL shortener is a small project with big lessons.&lt;/p&gt;

&lt;p&gt;You learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Database design&lt;/li&gt;
&lt;li&gt;Indexing&lt;/li&gt;
&lt;li&gt;Caching&lt;/li&gt;
&lt;li&gt;Distributed systems&lt;/li&gt;
&lt;li&gt;Load balancing&lt;/li&gt;
&lt;li&gt;Asynchronous processing&lt;/li&gt;
&lt;li&gt;Rate limiting&lt;/li&gt;
&lt;li&gt;System reliability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why system design interviews love URL shorteners.&lt;/p&gt;

&lt;p&gt;The application is simple.&lt;/p&gt;

&lt;p&gt;The engineering is not.&lt;/p&gt;




&lt;h1&gt;
  
  
  Final Thoughts
&lt;/h1&gt;

&lt;p&gt;The difference between a beginner implementation and a systems-engineered implementation is not the number of files or the complexity of the code.&lt;/p&gt;

&lt;p&gt;It is the ability to think about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scale&lt;/li&gt;
&lt;li&gt;Failure&lt;/li&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;li&gt;Trade-offs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A simple URL shortener can teach you more about backend architecture than many large projects.&lt;/p&gt;

&lt;p&gt;Because great engineers don't just build things that work.&lt;/p&gt;

&lt;p&gt;They build things that keep working when millions of people depend on them.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Data Structures That Made My APIs Faster</title>
      <dc:creator>Derek mwale</dc:creator>
      <pubDate>Wed, 22 Jul 2026 16:48:43 +0000</pubDate>
      <link>https://dev.to/derekmwale/data-structures-that-made-my-apis-faster-15gn</link>
      <guid>https://dev.to/derekmwale/data-structures-that-made-my-apis-faster-15gn</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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0ad483zjjgnoctbs9cd1.jpg" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0ad483zjjgnoctbs9cd1.jpg" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When developers talk about making APIs faster, the conversation usually goes straight to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding more servers&lt;/li&gt;
&lt;li&gt;Increasing database resources&lt;/li&gt;
&lt;li&gt;Adding caching&lt;/li&gt;
&lt;li&gt;Optimizing queries&lt;/li&gt;
&lt;li&gt;Using faster frameworks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those things matter.&lt;/p&gt;

&lt;p&gt;But sometimes the biggest performance improvement doesn't come from infrastructure.&lt;/p&gt;

&lt;p&gt;It comes from choosing the right way to store and access data.&lt;/p&gt;

&lt;p&gt;The data structures inside your application quietly decide how fast your API responds.&lt;/p&gt;

&lt;p&gt;A bad data structure can turn a millisecond operation into a second-long bottleneck.&lt;/p&gt;

&lt;p&gt;A good one can handle millions of operations effortlessly.&lt;/p&gt;

&lt;p&gt;Here are the data structures that have had the biggest impact on building faster APIs.&lt;/p&gt;




&lt;h1&gt;
  
  
  1. Hash Maps: The King of Fast Lookups
&lt;/h1&gt;

&lt;p&gt;One of the most useful data structures in backend development is the hash map.&lt;/p&gt;

&lt;p&gt;You probably use it every day without realizing it.&lt;/p&gt;

&lt;p&gt;In many languages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;HashMap&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;HashMap&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They all solve the same problem:&lt;/p&gt;

&lt;p&gt;"How do I find something quickly?"&lt;/p&gt;

&lt;p&gt;Imagine you have an API that retrieves users.&lt;/p&gt;

&lt;p&gt;A beginner approach might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bob&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Charlie&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;find_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works.&lt;/p&gt;

&lt;p&gt;Until you have millions of users.&lt;/p&gt;

&lt;p&gt;Every search requires scanning the entire list.&lt;/p&gt;

&lt;p&gt;The complexity is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;O(n)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A hash map changes everything.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bob&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Charlie&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the lookup is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;O(1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Constant time.&lt;/p&gt;

&lt;p&gt;The difference between searching one million records and instantly finding one record is enormous.&lt;/p&gt;




&lt;h1&gt;
  
  
  Real API Example: User Sessions
&lt;/h1&gt;

&lt;p&gt;Imagine an authentication service.&lt;/p&gt;

&lt;p&gt;Every request contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Authorization: Bearer token123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your API needs to find the user.&lt;/p&gt;

&lt;p&gt;A bad design:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request
 |
Search all sessions
 |
Find token
 |
Return user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A better design:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hash Map

token123 → User ID 5421
token456 → User ID 8821
token789 → User ID 9912
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now authentication becomes extremely fast.&lt;/p&gt;

&lt;p&gt;This is why caching systems like Redis are built around key-value lookups.&lt;/p&gt;




&lt;h1&gt;
  
  
  2. Queues: The Backbone of Scalable Systems
&lt;/h1&gt;

&lt;p&gt;Many APIs fail because they try to do everything immediately.&lt;/p&gt;

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

&lt;p&gt;A user uploads a video.&lt;/p&gt;

&lt;p&gt;Your API tries to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Save the video&lt;/li&gt;
&lt;li&gt;Compress it&lt;/li&gt;
&lt;li&gt;Generate thumbnails&lt;/li&gt;
&lt;li&gt;Send notifications&lt;/li&gt;
&lt;li&gt;Update analytics&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All before responding.&lt;/p&gt;

&lt;p&gt;The user waits.&lt;/p&gt;

&lt;p&gt;The server struggles.&lt;/p&gt;

&lt;p&gt;A queue changes the architecture.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;API Request

      |

      ▼

Add Job To Queue

      |

      ▼

Return Response

      |

      ▼

Background Workers Process Tasks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A queue follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;First In
First Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The oldest job gets processed first.&lt;/p&gt;

&lt;p&gt;Queues power:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Email systems&lt;/li&gt;
&lt;li&gt;Payment processing&lt;/li&gt;
&lt;li&gt;Video processing&lt;/li&gt;
&lt;li&gt;Notification systems&lt;/li&gt;
&lt;li&gt;Data pipelines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A good API doesn't always work harder.&lt;/p&gt;

&lt;p&gt;Sometimes it simply moves work somewhere smarter.&lt;/p&gt;




&lt;h1&gt;
  
  
  3. Trees: Making Search More Efficient
&lt;/h1&gt;

&lt;p&gt;Trees appear everywhere in backend systems.&lt;/p&gt;

&lt;p&gt;Databases use tree structures internally.&lt;/p&gt;

&lt;p&gt;File systems use trees.&lt;/p&gt;

&lt;p&gt;Search engines use trees.&lt;/p&gt;

&lt;p&gt;A common example is the B-Tree index.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'derek@example.com'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without an index:&lt;/p&gt;

&lt;p&gt;The database scans every row.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User 1
User 2
User 3
...
User 10,000,000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With an index:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;              M
           /     \
        A-M       N-Z
       /             \
   Derek          Sarah
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The database doesn't search everything.&lt;/p&gt;

&lt;p&gt;It follows a path.&lt;/p&gt;

&lt;p&gt;That is the magic of trees.&lt;/p&gt;




&lt;h1&gt;
  
  
  4. Sets: Eliminating Duplicate Work
&lt;/h1&gt;

&lt;p&gt;Sets are underrated.&lt;/p&gt;

&lt;p&gt;They solve a very common backend problem:&lt;/p&gt;

&lt;p&gt;"I only want unique values."&lt;/p&gt;

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

&lt;p&gt;A social media API recommends users to follow.&lt;/p&gt;

&lt;p&gt;You collect recommendations from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Friends&lt;/li&gt;
&lt;li&gt;Interests&lt;/li&gt;
&lt;li&gt;Location&lt;/li&gt;
&lt;li&gt;Trending users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same person might appear multiple times.&lt;/p&gt;

&lt;p&gt;Without a set:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;John
Sarah
John
Michael
Sarah
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With a set:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;John
Sarah
Michael
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instant cleanup.&lt;/p&gt;

&lt;p&gt;Sets are useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Removing duplicates&lt;/li&gt;
&lt;li&gt;Permission checks&lt;/li&gt;
&lt;li&gt;Feature flags&lt;/li&gt;
&lt;li&gt;User relationships&lt;/li&gt;
&lt;li&gt;Tracking processed events&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  5. Stacks: The Hidden Power Behind APIs
&lt;/h1&gt;

&lt;p&gt;Stacks follow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Last In
First Out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The newest item is handled first.&lt;/p&gt;

&lt;p&gt;You might not build a stack manually often, but they power many important systems.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Function calls&lt;/li&gt;
&lt;li&gt;Undo systems&lt;/li&gt;
&lt;li&gt;Expression evaluation&lt;/li&gt;
&lt;li&gt;Request processing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A practical API example:&lt;/p&gt;

&lt;p&gt;Imagine processing nested permissions:&lt;br&gt;
&lt;/p&gt;

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

  └── Manager

        └── Employee
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The system can use stack-based traversal to evaluate access rules.&lt;/p&gt;




&lt;h1&gt;
  
  
  6. Graphs: When Relationships Matter
&lt;/h1&gt;

&lt;p&gt;Modern applications are built on relationships.&lt;/p&gt;

&lt;p&gt;Social networks.&lt;/p&gt;

&lt;p&gt;Maps.&lt;/p&gt;

&lt;p&gt;Recommendations.&lt;/p&gt;

&lt;p&gt;Payments.&lt;/p&gt;

&lt;p&gt;All of these can be modeled as graphs.&lt;/p&gt;

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

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

 |
 |

Alice ---- Bob

 |
 |

Charlie
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A graph contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nodes&lt;/li&gt;
&lt;li&gt;Connections&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Social media:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Account → Transaction → Account
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Airport → Flight → Airport
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Recommendation engines are basically graph problems.&lt;/p&gt;




&lt;h1&gt;
  
  
  7. Priority Queues: Handling What Matters First
&lt;/h1&gt;

&lt;p&gt;Not every task has equal importance.&lt;/p&gt;

&lt;p&gt;A payment failure notification should probably happen before a marketing email.&lt;/p&gt;

&lt;p&gt;Priority queues solve this.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;High Priority

Payment Failed

Password Reset


Medium Priority

Order Update


Low Priority

Newsletter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The system always processes important tasks first.&lt;/p&gt;

&lt;p&gt;They power:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud scheduling&lt;/li&gt;
&lt;li&gt;Background jobs&lt;/li&gt;
&lt;li&gt;Gaming matchmaking&lt;/li&gt;
&lt;li&gt;Distributed systems&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Data Structures Are Architecture Decisions
&lt;/h1&gt;

&lt;p&gt;A common mistake is thinking:&lt;/p&gt;

&lt;p&gt;"Data structures are only for coding interviews."&lt;/p&gt;

&lt;p&gt;They are not.&lt;/p&gt;

&lt;p&gt;They are architecture decisions.&lt;/p&gt;

&lt;p&gt;Every time you build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An API&lt;/li&gt;
&lt;li&gt;A database&lt;/li&gt;
&lt;li&gt;A queue system&lt;/li&gt;
&lt;li&gt;A search feature&lt;/li&gt;
&lt;li&gt;A recommendation engine&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;you are choosing how information moves.&lt;/p&gt;

&lt;p&gt;The choice determines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Speed&lt;/li&gt;
&lt;li&gt;Scalability&lt;/li&gt;
&lt;li&gt;Memory usage&lt;/li&gt;
&lt;li&gt;Complexity&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  The Best Backend Engineers Think In Data Structures
&lt;/h1&gt;

&lt;p&gt;A junior developer asks:&lt;/p&gt;

&lt;p&gt;"How do I implement this feature?"&lt;/p&gt;

&lt;p&gt;An experienced engineer asks:&lt;/p&gt;

&lt;p&gt;"What is the right way to represent this problem?"&lt;/p&gt;

&lt;p&gt;That difference matters.&lt;/p&gt;

&lt;p&gt;A slow API is often not slow because the server is weak.&lt;/p&gt;

&lt;p&gt;Sometimes the problem is that the application is searching through lists when it should be using maps.&lt;/p&gt;

&lt;p&gt;Or doing synchronous work when it should use queues.&lt;/p&gt;

&lt;p&gt;Or scanning everything when it should use indexes.&lt;/p&gt;




&lt;h1&gt;
  
  
  Final Thoughts
&lt;/h1&gt;

&lt;p&gt;The fastest systems are not always built with the newest technologies.&lt;/p&gt;

&lt;p&gt;Sometimes the biggest performance improvements come from understanding the fundamentals.&lt;/p&gt;

&lt;p&gt;Hash maps for instant lookups.&lt;/p&gt;

&lt;p&gt;Queues for background processing.&lt;/p&gt;

&lt;p&gt;Trees for efficient searching.&lt;/p&gt;

&lt;p&gt;Sets for uniqueness.&lt;/p&gt;

&lt;p&gt;Graphs for relationships.&lt;/p&gt;

&lt;p&gt;Priority queues for intelligent scheduling.&lt;/p&gt;

&lt;p&gt;Data structures are not just computer science theory.&lt;/p&gt;

&lt;p&gt;They are the building blocks behind every fast API, scalable platform, and reliable system we use today.&lt;/p&gt;

&lt;p&gt;Before adding more servers, ask a simpler question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Am I storing and accessing my data the right way?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sometimes the fastest optimization is changing the way you think.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Designing a Notification System That Doesn't Fall Apart</title>
      <dc:creator>Derek mwale</dc:creator>
      <pubDate>Wed, 22 Jul 2026 16:35:18 +0000</pubDate>
      <link>https://dev.to/derekmwale/designing-a-notification-system-that-doesnt-fall-apart-3nkl</link>
      <guid>https://dev.to/derekmwale/designing-a-notification-system-that-doesnt-fall-apart-3nkl</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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjjaawgb01qgkrcvai4fq.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjjaawgb01qgkrcvai4fq.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every application eventually reaches the point where it needs notifications.&lt;/p&gt;

&lt;p&gt;At first, it feels simple.&lt;/p&gt;

&lt;p&gt;A user signs up? Send an email.&lt;/p&gt;

&lt;p&gt;Someone likes a post? Send a push notification.&lt;/p&gt;

&lt;p&gt;An order ships? Send an SMS.&lt;/p&gt;

&lt;p&gt;A payment fails? Notify the customer.&lt;/p&gt;

&lt;p&gt;So you write something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;createOrder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;sendEmail&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;sendPushNotification&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;sendSMS&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything works perfectly.&lt;/p&gt;

&lt;p&gt;Until it doesn't.&lt;/p&gt;

&lt;p&gt;The first few hundred users never expose the weaknesses in your design. But once your application starts growing, notifications become one of the hardest systems to maintain. Messages are sent twice. Others disappear completely. External providers fail. Users complain they never received important alerts. Suddenly, a feature that seemed trivial becomes responsible for some of the biggest production incidents.&lt;/p&gt;

&lt;p&gt;A notification system isn't just about sending messages.&lt;/p&gt;

&lt;p&gt;It's about delivering the right message, to the right user, at the right time, through the right channel, reliably.&lt;/p&gt;

&lt;p&gt;Here's how I'd build one.&lt;/p&gt;




&lt;h2&gt;
  
  
  The First Rule: Never Send Notifications Directly
&lt;/h2&gt;

&lt;p&gt;One of the biggest mistakes I see is tightly coupling business logic with notification logic.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OrderService
    ├── Save Order
    ├── Charge Card
    └── Send Email
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks harmless.&lt;/p&gt;

&lt;p&gt;Now imagine your email provider goes down.&lt;/p&gt;

&lt;p&gt;Should customers be prevented from placing orders because an email couldn't be delivered?&lt;/p&gt;

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

&lt;p&gt;Notifications should almost never be part of the critical request path.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Order Created
        │
        ▼
 Publish Event
        │
        ▼
 Notification Service
        │
        ├── Email
        ├── SMS
        └── Push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The order succeeds immediately.&lt;/p&gt;

&lt;p&gt;Notifications happen independently.&lt;/p&gt;

&lt;p&gt;That's a much healthier architecture.&lt;/p&gt;




&lt;h2&gt;
  
  
  Everything Starts With Events
&lt;/h2&gt;

&lt;p&gt;Think in events rather than actions.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;Send an email.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;OrderCreated happened.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That tiny mindset shift changes everything.&lt;/p&gt;

&lt;p&gt;Now multiple systems can react independently.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send an email.&lt;/li&gt;
&lt;li&gt;Send an SMS.&lt;/li&gt;
&lt;li&gt;Notify the warehouse.&lt;/li&gt;
&lt;li&gt;Update analytics.&lt;/li&gt;
&lt;li&gt;Award loyalty points.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nobody needs to know who is listening.&lt;/p&gt;

&lt;p&gt;Your application becomes far easier to extend.&lt;/p&gt;




&lt;h2&gt;
  
  
  Use Queues Everywhere
&lt;/h2&gt;

&lt;p&gt;External providers are slow.&lt;/p&gt;

&lt;p&gt;Some take two seconds.&lt;/p&gt;

&lt;p&gt;Some take twenty.&lt;/p&gt;

&lt;p&gt;Some randomly fail.&lt;/p&gt;

&lt;p&gt;If every request waits for those services, your API becomes painfully slow.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;API
 │
 ▼
Save Data
 │
 ▼
Queue Notification
 │
 ▼
Return Response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A background worker processes notifications independently.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Faster APIs&lt;/li&gt;
&lt;li&gt;Automatic retries&lt;/li&gt;
&lt;li&gt;Better scalability&lt;/li&gt;
&lt;li&gt;Failure isolation&lt;/li&gt;
&lt;li&gt;Easier monitoring&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Queues are one of the simplest improvements you can make to backend reliability.&lt;/p&gt;




&lt;h2&gt;
  
  
  Every Notification Needs a Lifecycle
&lt;/h2&gt;

&lt;p&gt;Notifications aren't simply "sent."&lt;/p&gt;

&lt;p&gt;They move through states.&lt;br&gt;
&lt;/p&gt;

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

Queued

Processing

Sent

Delivered

Failed

Retrying

Expired
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tracking these states helps answer questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why wasn't this email delivered?&lt;/li&gt;
&lt;li&gt;How many SMS messages failed today?&lt;/li&gt;
&lt;li&gt;Which notifications are stuck?&lt;/li&gt;
&lt;li&gt;How long does delivery usually take?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without lifecycle tracking, debugging becomes guesswork.&lt;/p&gt;




&lt;h2&gt;
  
  
  Design Around Multiple Channels
&lt;/h2&gt;

&lt;p&gt;Different users prefer different ways of being notified.&lt;/p&gt;

&lt;p&gt;Some want email.&lt;/p&gt;

&lt;p&gt;Others want push notifications.&lt;/p&gt;

&lt;p&gt;Some businesses require SMS.&lt;/p&gt;

&lt;p&gt;Tomorrow you may add Slack, WhatsApp, Microsoft Teams, or Discord.&lt;/p&gt;

&lt;p&gt;Avoid hardcoding providers.&lt;/p&gt;

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

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

Channel Interface

Email

SMS

Push

Slack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each channel implements the same interface.&lt;/p&gt;

&lt;p&gt;Adding a new notification type becomes a matter of plugging in another implementation rather than rewriting existing code.&lt;/p&gt;

&lt;p&gt;That's where design patterns like Strategy really shine.&lt;/p&gt;




&lt;h2&gt;
  
  
  Users Should Control Notifications
&lt;/h2&gt;

&lt;p&gt;Nothing annoys users more than endless alerts.&lt;/p&gt;

&lt;p&gt;A notification system should always respect preferences.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Marketing Emails

Order Updates

Security Alerts

Weekly Reports

Product Announcements
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each category should be independently configurable.&lt;/p&gt;

&lt;p&gt;Some notifications should never be disabled, such as password resets or fraud alerts.&lt;/p&gt;

&lt;p&gt;Everything else should be optional.&lt;/p&gt;

&lt;p&gt;Respecting user preferences builds trust.&lt;/p&gt;




&lt;h2&gt;
  
  
  Retries Matter More Than You Think
&lt;/h2&gt;

&lt;p&gt;Failures happen.&lt;/p&gt;

&lt;p&gt;Networks fail.&lt;/p&gt;

&lt;p&gt;SMTP servers fail.&lt;/p&gt;

&lt;p&gt;Push providers throttle requests.&lt;/p&gt;

&lt;p&gt;SMS gateways become unavailable.&lt;/p&gt;

&lt;p&gt;Don't give up after one attempt.&lt;/p&gt;

&lt;p&gt;Use exponential backoff.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Retry 1

1 minute

Retry 2

5 minutes

Retry 3

30 minutes

Retry 4

2 hours
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This reduces pressure on failing services and dramatically improves delivery success.&lt;/p&gt;




&lt;h2&gt;
  
  
  Never Lose Notifications
&lt;/h2&gt;

&lt;p&gt;Imagine a payment confirmation disappearing forever because the server restarted.&lt;/p&gt;

&lt;p&gt;That's unacceptable.&lt;/p&gt;

&lt;p&gt;Always persist notifications before processing.&lt;br&gt;
&lt;/p&gt;

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

↓

Queue

↓

Worker

↓

Provider
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the queue crashes, the notification still exists.&lt;/p&gt;

&lt;p&gt;If the worker crashes, processing resumes later.&lt;/p&gt;

&lt;p&gt;Durability is just as important as speed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prevent Duplicate Messages
&lt;/h2&gt;

&lt;p&gt;Retries introduce another challenge.&lt;/p&gt;

&lt;p&gt;Duplicate notifications.&lt;/p&gt;

&lt;p&gt;Nobody wants five identical emails saying:&lt;/p&gt;

&lt;p&gt;"Your payment was successful."&lt;/p&gt;

&lt;p&gt;Use idempotency.&lt;/p&gt;

&lt;p&gt;Every notification should have a unique identifier.&lt;/p&gt;

&lt;p&gt;Before sending, check whether that notification has already been successfully delivered.&lt;/p&gt;

&lt;p&gt;Processing the same event twice should still produce only one user-facing message.&lt;/p&gt;




&lt;h2&gt;
  
  
  Separate Templates From Code
&lt;/h2&gt;

&lt;p&gt;Hardcoding notification text quickly becomes painful.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;sendEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello John, your order has shipped...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use templates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Template:
Order Shipped

Variables:
Customer Name
Tracking Number
Courier
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows designers, marketers, or support teams to update messaging without touching application code.&lt;/p&gt;

&lt;p&gt;It's also essential if your application supports multiple languages.&lt;/p&gt;




&lt;h2&gt;
  
  
  Monitor Everything
&lt;/h2&gt;

&lt;p&gt;A notification system without observability is impossible to operate.&lt;/p&gt;

&lt;p&gt;Track metrics such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Delivery rate&lt;/li&gt;
&lt;li&gt;Failure rate&lt;/li&gt;
&lt;li&gt;Retry count&lt;/li&gt;
&lt;li&gt;Queue size&lt;/li&gt;
&lt;li&gt;Processing time&lt;/li&gt;
&lt;li&gt;Provider latency&lt;/li&gt;
&lt;li&gt;Bounce rate&lt;/li&gt;
&lt;li&gt;Open rate (where applicable)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Good dashboards often reveal problems long before users notice them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Scaling Is Easier Than You Think
&lt;/h2&gt;

&lt;p&gt;One beautiful aspect of queue-based systems is horizontal scaling.&lt;/p&gt;

&lt;p&gt;One worker processes 100 notifications per minute.&lt;/p&gt;

&lt;p&gt;Need more?&lt;/p&gt;

&lt;p&gt;Run five workers.&lt;/p&gt;

&lt;p&gt;Need even more?&lt;/p&gt;

&lt;p&gt;Run fifty.&lt;/p&gt;

&lt;p&gt;No changes to your application code.&lt;/p&gt;

&lt;p&gt;That's one of the biggest reasons modern distributed systems rely so heavily on message queues.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Simple Architecture
&lt;/h2&gt;

&lt;p&gt;Putting everything together, the architecture looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Application
        │
        ▼
Event Bus
        │
        ▼
Notification Queue
        │
        ▼
Notification Workers
        │
        ▼
Email | SMS | Push | Slack
        │
        ▼
Delivery Status Database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each component has a single responsibility.&lt;/p&gt;

&lt;p&gt;The application creates events.&lt;/p&gt;

&lt;p&gt;The queue guarantees reliable processing.&lt;/p&gt;

&lt;p&gt;Workers send notifications.&lt;/p&gt;

&lt;p&gt;Providers deliver messages.&lt;/p&gt;

&lt;p&gt;The database tracks everything.&lt;/p&gt;

&lt;p&gt;Each layer can evolve independently.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Notifications look like a small feature until your product starts growing.&lt;/p&gt;

&lt;p&gt;Then they become one of the busiest systems in your entire platform.&lt;/p&gt;

&lt;p&gt;The difference between a notification system that scales and one that constantly breaks usually isn't a fancy technology or a complex algorithm. It's thoughtful architecture.&lt;/p&gt;

&lt;p&gt;Decouple your business logic.&lt;/p&gt;

&lt;p&gt;Think in events.&lt;/p&gt;

&lt;p&gt;Use queues.&lt;/p&gt;

&lt;p&gt;Design for retries.&lt;/p&gt;

&lt;p&gt;Make operations idempotent.&lt;/p&gt;

&lt;p&gt;Respect user preferences.&lt;/p&gt;

&lt;p&gt;Measure everything.&lt;/p&gt;

&lt;p&gt;Build it this way from the beginning, and your notification system won't just send messages—it will keep doing its job reliably, even as your application grows from hundreds of users to millions.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>scalability</category>
      <category>systemdesign</category>
    </item>
  </channel>
</rss>
