<?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: Gouranga Das Samrat</title>
    <description>The latest articles on DEV Community by Gouranga Das Samrat (@gouranga-das-khulna).</description>
    <link>https://dev.to/gouranga-das-khulna</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%2F2193879%2Ff1ee673c-8205-4c86-b558-de345a9d4490.jpg</url>
      <title>DEV Community: Gouranga Das Samrat</title>
      <link>https://dev.to/gouranga-das-khulna</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gouranga-das-khulna"/>
    <language>en</language>
    <item>
      <title>Distributed Cron Jobs</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Sun, 18 Oct 2026 04:00:00 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/distributed-cron-jobs-24ol</link>
      <guid>https://dev.to/gouranga-das-khulna/distributed-cron-jobs-24ol</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Regular cron runs on one server. What happens when you have 10 servers? Each runs the job 10 times. That's a problem.&lt;/p&gt;
&lt;/blockquote&gt;




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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Single server cron: ✅ Job runs once at 2am
10-server fleet:    ❌ Job runs 10 times at 2am — duplicate emails, double charges!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Dedicated Scheduler Node
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;One designated machine runs all cron jobs&lt;/li&gt;
&lt;li&gt;✅ Simple&lt;/li&gt;
&lt;li&gt;❌ Single point of failure — if this node dies, no cron jobs run&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Leader Election + Cron
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Cluster elects a leader (using etcd/ZooKeeper)&lt;/li&gt;
&lt;li&gt;Only the leader runs cron jobs&lt;/li&gt;
&lt;li&gt;If leader dies → new leader elected → cron resumes&lt;/li&gt;
&lt;li&gt;✅ No SPOF | ❌ Leader election complexity&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Distributed Lock Before Job Execution
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_job&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;lock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cron:daily-email&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;locked&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# 5min TTL
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;  &lt;span class="c1"&gt;# another node is running it
&lt;/span&gt;    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;send_daily_emails&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cron:daily-email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;✅ Simple, works with existing Redis&lt;/li&gt;
&lt;li&gt;❌ Lock expiry must be &amp;gt; job duration, or use heartbeat extension&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Dedicated Scheduling Services
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AWS EventBridge Scheduler&lt;/strong&gt; — cron without servers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Temporal.io&lt;/strong&gt; — workflow orchestration with scheduling&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Airflow&lt;/strong&gt; — DAG-based job scheduling&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sidekiq-Cron&lt;/strong&gt; (Ruby), &lt;strong&gt;Bull&lt;/strong&gt; (Node.js)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Exactly-Once Execution
&lt;/h2&gt;

&lt;p&gt;For critical jobs (billing, emails):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use idempotency keys in the job itself&lt;/li&gt;
&lt;li&gt;Record execution in DB before running: &lt;code&gt;INSERT INTO job_runs (job_id, run_date) ON CONFLICT DO NOTHING&lt;/code&gt; → if 0 rows inserted, skip&lt;/li&gt;
&lt;li&gt;Use a distributed lock with heartbeat&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Observability for Cron
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Alert if a job DIDN'T run (missed heartbeat)&lt;/li&gt;
&lt;li&gt;Track job duration — sudden increase = something is wrong&lt;/li&gt;
&lt;li&gt;Log job result (success/failure, records processed)&lt;/li&gt;
&lt;li&gt;Tool: &lt;strong&gt;Healthchecks.io&lt;/strong&gt; — cron monitoring via ping&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>systemdesign</category>
      <category>distributedsystems</category>
      <category>backend</category>
      <category>api</category>
    </item>
    <item>
      <title>Cache Invalidation Patterns</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Sat, 17 Oct 2026 04:00:00 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/cache-invalidation-patterns-5bi6</link>
      <guid>https://dev.to/gouranga-das-khulna/cache-invalidation-patterns-5bi6</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;"There are only two hard things in computer science: cache invalidation and naming things." — Phil Karlton&lt;/p&gt;
&lt;/blockquote&gt;




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

&lt;p&gt;Cache = stale data risk. Every caching strategy is a trade-off between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Freshness&lt;/strong&gt; — how up-to-date is cached data?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt; — how often do we go to the DB?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistency&lt;/strong&gt; — does every user see the same thing?&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Strategy 1: TTL (Time-To-Live) Expiry
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user:123&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# expires in 5 minutes
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Simplest strategy — let cache entries age out&lt;/li&gt;
&lt;li&gt;✅ No invalidation logic needed&lt;/li&gt;
&lt;li&gt;❌ Stale window = TTL duration (user sees old data for up to 5 min)&lt;/li&gt;
&lt;li&gt;❌ Cache stampede on expiry (see below)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Choose TTL by data freshness requirement:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User profile: 5-15 minutes&lt;/li&gt;
&lt;li&gt;Product price: 1-5 minutes&lt;/li&gt;
&lt;li&gt;News article: 1 hour&lt;/li&gt;
&lt;li&gt;Static config: 1 day&lt;/li&gt;
&lt;li&gt;Currency rates: 1 minute&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Strategy 2: Write-Through Cache
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Application writes → Cache AND DB simultaneously
Read → always hits cache (always warm)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;✅ Cache always up-to-date (no stale reads)&lt;/li&gt;
&lt;li&gt;✅ Reads always fast&lt;/li&gt;
&lt;li&gt;❌ Write latency doubles (must write both)&lt;/li&gt;
&lt;li&gt;❌ Cache may fill with data never read (write-heavy workloads waste memory)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Read-heavy workloads where writes are infrequent&lt;/p&gt;




&lt;h2&gt;
  
  
  Strategy 3: Write-Behind (Write-Back) Cache
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Application writes → Cache only (async)
Background worker → flushes cache to DB periodically
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;✅ Very fast writes (no DB in critical path)&lt;/li&gt;
&lt;li&gt;❌ Data loss risk if cache crashes before flush&lt;/li&gt;
&lt;li&gt;❌ Complexity — need background flusher, failure handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; High-write scenarios where some data loss is acceptable (analytics, counters)&lt;/p&gt;




&lt;h2&gt;
  
  
  Strategy 4: Cache-Aside (Lazy Loading)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Read request:
  Check cache → HIT: return ✅
              → MISS: query DB → store in cache → return

Write request:
  Write to DB
  Invalidate (delete) cache entry
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Most common pattern&lt;/li&gt;
&lt;li&gt;✅ Cache only contains data that's actually requested&lt;/li&gt;
&lt;li&gt;✅ Cache failure doesn't affect writes&lt;/li&gt;
&lt;li&gt;❌ Cache miss = extra DB round trip (cold start penalty)&lt;/li&gt;
&lt;li&gt;❌ Race condition: two reads can populate stale data simultaneously&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Race condition fix:&lt;/strong&gt; Use a short TTL even when invalidating, or use versioned keys.&lt;/p&gt;




&lt;h2&gt;
  
  
  Strategy 5: Event-Driven Invalidation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DB changes → emit event (via Kafka, SNS, CDC) → cache service → delete/update cache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;✅ Cache invalidated immediately on change&lt;/li&gt;
&lt;li&gt;✅ Decoupled — cache logic separate from write logic&lt;/li&gt;
&lt;li&gt;❌ Event delay = brief stale window&lt;/li&gt;
&lt;li&gt;❌ Event loss = permanently stale cache (need retry/DLQ)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;CDC (Change Data Capture):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Debezium reads Postgres WAL → emits change events → Kafka → cache invalidation service&lt;/li&gt;
&lt;li&gt;Low-latency, no application code change required&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚡ Cache Stampede (Thundering Herd)
&lt;/h2&gt;

&lt;p&gt;When a popular cache key expires → thousands of concurrent requests all hit DB simultaneously → DB overloaded → slow responses → everyone waits → chaos.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Mutex/Lock on Cache Miss
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_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="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&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;data&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;data&lt;/span&gt;

    &lt;span class="c1"&gt;# Acquire lock — only one thread fetches from DB
&lt;/span&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lock:user:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# double-check after lock
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;data&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;data&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_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="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;300&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;data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Early Expiry / Probabilistic Refresh
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Refresh cache before it actually expires&lt;/li&gt;
&lt;li&gt;Background thread proactively refreshes popular keys at ~80% of TTL&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Serve stale data immediately&lt;/li&gt;
&lt;li&gt;Async: fetch fresh data in background, update cache&lt;/li&gt;
&lt;li&gt;Users see slightly stale but fast response&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Strategy 6: Versioned Cache Keys
&lt;/h2&gt;

&lt;p&gt;Instead of invalidating → use new key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# v1 data at key: user:123:v1&lt;/span&gt;
&lt;span class="c"&gt;# After update → write to user:123:v2&lt;/span&gt;
&lt;span class="c"&gt;# Old key auto-expires, new key is fresh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;✅ No invalidation race conditions&lt;/li&gt;
&lt;li&gt;✅ Old and new data can coexist during rollout&lt;/li&gt;
&lt;li&gt;❌ Old keys accumulate (need GC / short TTL on old versions)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚖️ Summary — Which Pattern When?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pattern&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;TTL&lt;/td&gt;
&lt;td&gt;Simple cases, infrequent updates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Write-Through&lt;/td&gt;
&lt;td&gt;Read-heavy, must-be-fresh&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Write-Behind&lt;/td&gt;
&lt;td&gt;High write throughput, some loss OK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache-Aside&lt;/td&gt;
&lt;td&gt;General purpose ← &lt;strong&gt;default choice&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Event-driven&lt;/td&gt;
&lt;td&gt;Complex systems, CDC, microservices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Versioned keys&lt;/td&gt;
&lt;td&gt;Zero-downtime cache updates&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Default interview answer:&lt;/strong&gt; Cache-aside + TTL + event-driven invalidation for critical data.&lt;/p&gt;




</description>
      <category>api</category>
      <category>backend</category>
      <category>systemdesign</category>
      <category>distributedsystems</category>
    </item>
    <item>
      <title>API Design — Advanced</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Sun, 11 Oct 2026 04:00:00 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/api-design-advanced-86f</link>
      <guid>https://dev.to/gouranga-das-khulna/api-design-advanced-86f</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;You know the basics. Here's what separates good API design from great API design.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  📄 Pagination Strategies
&lt;/h2&gt;

&lt;p&gt;Never return unbounded lists. Always paginate.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Offset-Based Pagination
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /posts?limit=20&amp;amp;offset=40
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Simple, easy to implement&lt;/li&gt;
&lt;li&gt;✅ Jump to any page directly ("go to page 5")&lt;/li&gt;
&lt;li&gt;❌ &lt;strong&gt;Page drift:&lt;/strong&gt; if items are added/deleted between requests, you miss or duplicate items&lt;/li&gt;
&lt;li&gt;❌ Performance degrades at high offsets (&lt;code&gt;OFFSET 100000&lt;/code&gt; scans 100k rows and discards them)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use when:&lt;/strong&gt; small datasets, admin panels, search results&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Cursor-Based Pagination (Recommended for feeds)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /posts?limit=20&amp;amp;cursor=eyJpZCI6MTIzfQ==
Response: { data: [...], nextCursor: "eyJpZCI6MTQ0fQ==" }
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Cursor = encoded pointer to last item seen (e.g., base64 of &lt;code&gt;{id: 123}&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;✅ Stable — no page drift even if new items inserted&lt;/li&gt;
&lt;li&gt;✅ Efficient — WHERE id &amp;gt; 123 LIMIT 20 uses index perfectly&lt;/li&gt;
&lt;li&gt;❌ Can't jump to arbitrary pages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use when:&lt;/strong&gt; infinite scroll, Twitter/Instagram feeds, real-time data&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Keyset Pagination
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Variant of cursor — uses actual column values (not encoded)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /posts?limit=20&amp;amp;after_id=123&amp;amp;after_created_at=2024-01-15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Multi-column sort support&lt;/li&gt;
&lt;li&gt;Works naturally with DB indexes&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Page-Based (Simple)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /posts?page=3&amp;amp;per_page=20
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Like offset but friendlier naming&lt;/li&gt;
&lt;li&gt;Same problems as offset&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔍 Filtering &amp;amp; Sorting
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Filtering Patterns
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;# Simple equality
GET /users?status=active&amp;amp;role=admin

# Range filters
GET /orders?created_after=2024-01-01&amp;amp;created_before=2024-12-31
GET /products?price_min=10&amp;amp;price_max=100

# Multi-value
GET /products?category=electronics,phones

# Search
GET /users?search=john
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;DB implications:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each filter = potential WHERE clause&lt;/li&gt;
&lt;li&gt;Ensure composite indexes match common filter combinations&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;status + role&lt;/code&gt; both filtered → composite index &lt;code&gt;(status, role)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Sorting
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /products?sort=price&amp;amp;order=asc
GET /products?sort=-created_at          # prefix - for desc
GET /products?sort=price,-created_at    # multi-sort
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Sort key must be indexed (or full table scan)&lt;/li&gt;
&lt;li&gt;For cursor pagination: sort field must be part of the cursor&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📊 GraphQL Basics
&lt;/h2&gt;

&lt;p&gt;REST: client gets what the server decides to send.&lt;br&gt;
GraphQL: client asks for exactly what it needs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="c"&gt;# REST: GET /users/123 returns ALL user fields&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# GraphQL: client specifies exactly what it wants&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;query&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;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"123"&lt;/span&gt;&lt;span class="p"&gt;)&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;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&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;span class="n"&gt;title&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;createdAt&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;span class="p"&gt;}&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;&lt;strong&gt;Problems GraphQL solves:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Over-fetching:&lt;/strong&gt; REST returns 50 fields, you need 3&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Under-fetching:&lt;/strong&gt; Need to call 3 REST endpoints to build one page&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type safety:&lt;/strong&gt; Schema defines exactly what's available&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When to use GraphQL:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple clients (mobile, web, third-party) with different data needs&lt;/li&gt;
&lt;li&gt;Rapidly evolving APIs (add fields without breaking clients)&lt;/li&gt;
&lt;li&gt;Complex, interconnected data (think: social graph)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When to stick with REST:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple CRUD APIs&lt;/li&gt;
&lt;li&gt;Public APIs (REST is more universally understood)&lt;/li&gt;
&lt;li&gt;File uploads, streaming (REST handles these better)&lt;/li&gt;
&lt;li&gt;Small team — GraphQL has operational overhead&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;N+1 Problem:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&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;span class="n"&gt;users&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;span class="n"&gt;posts&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;span class="n"&gt;comments&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;span class="p"&gt;}&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;span class="c"&gt;# Without DataLoader: 1 + N + N*M queries 🔥&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# With DataLoader: batch loads → 3 queries total ✅&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🏷️ API Versioning
&lt;/h2&gt;

&lt;p&gt;You mentioned this — here's the full picture:&lt;/p&gt;

&lt;h3&gt;
  
  
  URL Versioning (Most common)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /v1/users
GET /v2/users
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;✅ Very explicit, easy to route&lt;/li&gt;
&lt;li&gt;❌ URL "should" be a resource, not a version&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Header Versioning
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /users
Accept: application/vnd.myapi.v2+json
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;✅ Clean URLs&lt;/li&gt;
&lt;li&gt;❌ Harder to test (can't just paste URL in browser)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Query Parameter
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /users?version=2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;✅ Easy to test&lt;/li&gt;
&lt;li&gt;❌ Optional params = easy to forget → inconsistent behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Sunset Policy
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Announce deprecation date for old versions&lt;/li&gt;
&lt;li&gt;Return &lt;code&gt;Deprecation&lt;/code&gt; and &lt;code&gt;Sunset&lt;/code&gt; headers on old endpoints&lt;/li&gt;
&lt;li&gt;Give clients 6–12 months to migrate&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔒 API Best Practices (Interview Checklist)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Topic&lt;/th&gt;
&lt;th&gt;Best Practice&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Auth&lt;/td&gt;
&lt;td&gt;Bearer token in &lt;code&gt;Authorization&lt;/code&gt; header, not URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Errors&lt;/td&gt;
&lt;td&gt;Consistent error format: &lt;code&gt;{ error: { code, message, details } }&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rate Limiting&lt;/td&gt;
&lt;td&gt;Return &lt;code&gt;Retry-After&lt;/code&gt; header, 429 status&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Idempotency&lt;/td&gt;
&lt;td&gt;POST with &lt;code&gt;Idempotency-Key&lt;/code&gt; header for safe retries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Status Codes&lt;/td&gt;
&lt;td&gt;Use them correctly: 201 Created, 204 No Content, 409 Conflict&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HATEOAS&lt;/td&gt;
&lt;td&gt;Return links to related resources (optional but impressive)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compression&lt;/td&gt;
&lt;td&gt;gzip responses &amp;gt; 1KB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  ⚖️ Trade-offs
&lt;/h2&gt;

&lt;p&gt;⚖️ &lt;strong&gt;REST vs GraphQL at interview:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Default to REST for simplicity&lt;/li&gt;
&lt;li&gt;Propose GraphQL when: multiple client types, complex data graph, bandwidth-sensitive (mobile)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚖️ &lt;strong&gt;Offset vs Cursor pagination:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Default to cursor for production feeds&lt;/li&gt;
&lt;li&gt;Use offset for admin/search (random access needed)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>systemdesign</category>
      <category>distributedsystems</category>
      <category>api</category>
      <category>backend</category>
    </item>
    <item>
      <title>Failure Handling &amp; Resilience</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Sat, 10 Oct 2026 04:00:00 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/failure-handling-resilience-4p8h</link>
      <guid>https://dev.to/gouranga-das-khulna/failure-handling-resilience-4p8h</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Interviewers LOVE failure thinking 😏 — "What happens when X fails?" is the classic follow-up.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Mindset
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Design for failure, not for success.&lt;/strong&gt;&lt;br&gt;
Every component WILL fail. The question is: does one failure cause total system failure, or does the system degrade gracefully?&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🔁 Retry Strategies
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Naive Retry (❌ Don't do this)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request fails → immediately retry → retry → retry → retry
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Hammers a struggling service → makes it worse&lt;/li&gt;
&lt;li&gt;Can cause &lt;strong&gt;retry storms&lt;/strong&gt; (10k clients all retrying at once)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Exponential Backoff (✅ Standard)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Attempt 1: fail → wait 1s
Attempt 2: fail → wait 2s
Attempt 3: fail → wait 4s
Attempt 4: fail → wait 8s → give up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Wait time doubles each attempt&lt;/li&gt;
&lt;li&gt;Reduces load on recovering service&lt;/li&gt;
&lt;li&gt;Formula: &lt;code&gt;wait = baseDelay * 2^attempt&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Exponential Backoff + Jitter (✅ Best)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wait = random(0, baseDelay * 2^attempt)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Randomness prevents thundering herd (all clients retrying at exact same moment)&lt;/li&gt;
&lt;li&gt;AWS SDK uses this by default&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Retry Budget
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Cap total retries across all clients (e.g., max 10% of requests can be retries)&lt;/li&gt;
&lt;li&gt;Prevents cascading retry storms at scale&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What to retry:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Transient errors: network timeout, 429 (rate limited), 503 (service unavailable)&lt;/li&gt;
&lt;li&gt;❌ Don't retry: 400 (bad request), 401 (auth), 404 (not found) — retrying won't help&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📬 Dead Letter Queues (DLQ)
&lt;/h2&gt;

&lt;p&gt;When a message in a queue fails processing repeatedly → route it to a DLQ instead of losing it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SQS Queue → Consumer processes message
              → Success: delete from queue ✅
              → Fail (3 times): move to DLQ 📦
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;DLQ allows:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inspect failed messages to find bugs&lt;/li&gt;
&lt;li&gt;Replay messages after fixing the bug&lt;/li&gt;
&lt;li&gt;Alert on DLQ depth (metric = something is broken)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Set up:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;maxReceiveCount&lt;/code&gt; = how many times to attempt before DLQ&lt;/li&gt;
&lt;li&gt;Separate queue for dead letters (same type as source)&lt;/li&gt;
&lt;li&gt;CloudWatch alarm on &lt;code&gt;ApproximateNumberOfMessagesVisible&lt;/code&gt; in DLQ&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🌊 Graceful Degradation
&lt;/h2&gt;

&lt;p&gt;When a non-critical dependency fails, the system keeps working in reduced capacity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples:
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Bad (total failure)&lt;/th&gt;
&lt;th&gt;Good (graceful)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Recommendation service down&lt;/td&gt;
&lt;td&gt;Whole page errors&lt;/td&gt;
&lt;td&gt;Show popular items instead&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reviews service down&lt;/td&gt;
&lt;td&gt;Product page errors&lt;/td&gt;
&lt;td&gt;Hide review section, show product&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Payment provider slow&lt;/td&gt;
&lt;td&gt;Checkout hangs&lt;/td&gt;
&lt;td&gt;Show "processing, email confirmation coming"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Search index down&lt;/td&gt;
&lt;td&gt;500 error&lt;/td&gt;
&lt;td&gt;Fall back to basic DB query&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Key question in interview:&lt;/strong&gt; "Which parts of your system are critical vs. nice-to-have?"&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Critical: checkout, auth, core data reads&lt;/li&gt;
&lt;li&gt;Non-critical: recommendations, analytics, social features&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Feature Flags for Degradation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;feature_enabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;recommendations&lt;/span&gt;&lt;span class="dl"&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;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getRecommendations&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;getPopularItems&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// fallback&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Toggle features off instantly without a deploy.&lt;/p&gt;




&lt;h2&gt;
  
  
  🐒 Chaos Engineering
&lt;/h2&gt;

&lt;p&gt;Intentionally inject failures in production (or staging) to find weaknesses before real incidents do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Principle:&lt;/strong&gt; You don't know if your failover works until you've tested it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Process:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Hypothesis:&lt;/strong&gt; "If the recommendations service goes down, users can still checkout"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inject:&lt;/strong&gt; Kill the recommendations service&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observe:&lt;/strong&gt; What breaks? What degrades? What alerts fire?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fix:&lt;/strong&gt; Improve resilience based on findings&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Repeat&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Tools:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Netflix Chaos Monkey&lt;/strong&gt; — randomly kills EC2 instances&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gremlin&lt;/strong&gt; — controlled chaos (network latency, CPU spike, pod kills)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Fault Injection Simulator&lt;/strong&gt; — managed chaos on AWS&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Starting points (low risk):
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Kill a non-critical service and verify degradation works&lt;/li&gt;
&lt;li&gt;Add 200ms latency to a downstream call and verify timeouts fire&lt;/li&gt;
&lt;li&gt;Simulate a DB read replica failure — does traffic shift to primary?&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛡️ Bulkhead Pattern
&lt;/h2&gt;

&lt;p&gt;Isolate components so one failure doesn't drain all shared resources.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Without bulkhead:
  Slow service B fills all 100 thread pool slots
  → Service A and C requests also fail (no threads left)

With bulkhead:
  Service A: 33 threads
  Service B: 33 threads  ← B fills its own threads, doesn't affect others
  Service C: 33 threads
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Applied via: separate thread pools, separate connection pools, Kubernetes resource limits.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⏱️ Timeout Everything
&lt;/h2&gt;

&lt;p&gt;Every network call must have a timeout. No exception.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Connection timeout:&lt;/strong&gt; how long to wait to establish connection (~5s)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read timeout:&lt;/strong&gt; how long to wait for response after connecting (~30s)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overall request timeout:&lt;/strong&gt; end-to-end budget per request&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without timeouts: one slow service causes thread starvation across the whole system.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚖️ Trade-offs
&lt;/h2&gt;

&lt;p&gt;✅ &lt;strong&gt;Pros of resilience patterns&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;System stays up even when parts fail&lt;/li&gt;
&lt;li&gt;Better user experience under degraded conditions&lt;/li&gt;
&lt;li&gt;Faster incident recovery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❌ &lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More complex code (retry logic, fallbacks)&lt;/li&gt;
&lt;li&gt;More infrastructure (DLQs, circuit breakers)&lt;/li&gt;
&lt;li&gt;Chaos engineering requires cultural buy-in&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚖️ &lt;strong&gt;Interview tip&lt;/strong&gt;&lt;br&gt;
When you describe any component → follow up with: "And if this fails, here's what happens..." — this instantly signals senior thinking.&lt;/p&gt;




</description>
      <category>systemdesign</category>
      <category>distributedsystems</category>
      <category>backend</category>
      <category>devops</category>
    </item>
    <item>
      <title>Edge Computing</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Sun, 04 Oct 2026 04:00:00 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/edge-computing-4beh</link>
      <guid>https://dev.to/gouranga-das-khulna/edge-computing-4beh</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;CDN serves static files. Edge computing runs &lt;strong&gt;logic&lt;/strong&gt; at the edge. This is the next level.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  CDN vs Edge Computing
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;CDN&lt;/th&gt;
&lt;th&gt;Edge Computing&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;What it does&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Caches static files (HTML, JS, images)&lt;/td&gt;
&lt;td&gt;Runs code at edge nodes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dynamic content&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Must go to origin&lt;/td&gt;
&lt;td&gt;✅ Can compute at edge&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Latency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Low for cache hits&lt;/td&gt;
&lt;td&gt;Low even for dynamic responses&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Examples&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;CloudFront, Fastly&lt;/td&gt;
&lt;td&gt;Cloudflare Workers, Lambda@Edge, Deno Deploy&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🧠 Edge Functions
&lt;/h2&gt;

&lt;p&gt;Code that runs in the CDN network, geographically close to users.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cloudflare Workers&lt;/strong&gt; — V8 isolates, JS/WASM, 0ms cold start&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lambda@Edge&lt;/strong&gt; — AWS, triggered by CloudFront, higher cold starts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vercel Edge Functions&lt;/strong&gt; — built on Cloudflare Workers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deno Deploy&lt;/strong&gt; — TypeScript-native&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;No filesystem access&lt;/li&gt;
&lt;li&gt;Limited CPU time (1–50ms budgets)&lt;/li&gt;
&lt;li&gt;Limited memory (~128MB)&lt;/li&gt;
&lt;li&gt;No long-running processes&lt;/li&gt;
&lt;li&gt;Some have no Node.js APIs (use Web APIs only)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔑 Use Cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Authentication &amp;amp; Authorization at the Edge
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User → Edge Node → check JWT → valid? → forward to origin
                              invalid? → return 401 immediately
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Block unauthenticated requests before they hit your servers&lt;/li&gt;
&lt;li&gt;No round-trip to origin for auth validation&lt;/li&gt;
&lt;li&gt;Reduces load on origin by rejecting bad requests early&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Personalization
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User request hits edge →
  Read cookie / geo / device header →
  Rewrite URL or inject headers →
  Serve personalized variant
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;A/B testing without origin involvement&lt;/li&gt;
&lt;li&gt;Locale-based content (language, currency)&lt;/li&gt;
&lt;li&gt;Device-based content (mobile vs desktop)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Bot Detection &amp;amp; Rate Limiting
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Block bots at the edge before they consume origin resources&lt;/li&gt;
&lt;li&gt;Cloudflare's Bot Management runs entirely at edge&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Request/Response Transformation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add security headers (CSP, HSTS) to every response&lt;/li&gt;
&lt;li&gt;Strip sensitive headers before forwarding&lt;/li&gt;
&lt;li&gt;Rewrite URLs for legacy compatibility&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Geo-Based Redirects
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Cloudflare Worker example&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&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;country&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;country&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;country&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DE&lt;/span&gt;&lt;span class="dl"&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;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://de.example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🗺️ Edge vs Origin Decision Tree
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Is the response the same for all users?
  YES → CDN cache it (static)
  NO  → Does personalization need server state/DB?
          NO  → Edge function (compute from request headers/cookies)
          YES → Origin server (but edge can cache origin response per variant)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📦 Edge KV Storage
&lt;/h2&gt;

&lt;p&gt;Some edge platforms offer distributed key-value stores accessible from edge:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cloudflare KV&lt;/strong&gt; — globally replicated, eventual consistency, low-latency reads&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloudflare Durable Objects&lt;/strong&gt; — strongly consistent, single-region, great for coordination&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Feature flags&lt;/li&gt;
&lt;li&gt;Rate limit counters (approximate)&lt;/li&gt;
&lt;li&gt;Session data&lt;/li&gt;
&lt;li&gt;Config that changes infrequently&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚖️ Trade-offs
&lt;/h2&gt;

&lt;p&gt;✅ &lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sub-10ms response for many use cases&lt;/li&gt;
&lt;li&gt;Reduces load and cost on origin servers&lt;/li&gt;
&lt;li&gt;No infrastructure to manage (serverless)&lt;/li&gt;
&lt;li&gt;Global presence instantly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❌ &lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No access to databases or internal services directly&lt;/li&gt;
&lt;li&gt;Limited runtime environment (no full Node.js)&lt;/li&gt;
&lt;li&gt;Debugging is harder (distributed, remote)&lt;/li&gt;
&lt;li&gt;Cold start exists (minimal but nonzero for Lambda@Edge)&lt;/li&gt;
&lt;li&gt;Vendor lock-in (Cloudflare Workers API ≠ Lambda@Edge API)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚖️ &lt;strong&gt;When to use&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auth validation, bot blocking, geo-redirects&lt;/li&gt;
&lt;li&gt;A/B testing, personalization headers&lt;/li&gt;
&lt;li&gt;Performance-critical responses that don't need DB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When NOT to use&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complex business logic requiring DB queries&lt;/li&gt;
&lt;li&gt;Long-running operations&lt;/li&gt;
&lt;li&gt;When you need full OS / filesystem access&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>systemdesign</category>
      <category>distributedsystems</category>
      <category>backend</category>
    </item>
    <item>
      <title>Cost Optimization</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Sat, 03 Oct 2026 04:00:00 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/cost-optimization-onl</link>
      <guid>https://dev.to/gouranga-das-khulna/cost-optimization-onl</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Most candidates ignore this — huge differentiator 🔥 Interviewers love candidates who think about cost.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Mindset: Performance vs Cost
&lt;/h2&gt;

&lt;p&gt;Every design decision has a cost. Good engineers think in &lt;strong&gt;cost per unit of work&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Don't just ask: "What's the most scalable solution?"
Ask:            "What's the most scalable solution FOR THIS BUDGET?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧮 Cost vs Performance Trade-offs
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Caching vs Compute
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;th&gt;Latency&lt;/th&gt;
&lt;th&gt;Freshness&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Compute every request&lt;/td&gt;
&lt;td&gt;High CPU cost&lt;/td&gt;
&lt;td&gt;Higher&lt;/td&gt;
&lt;td&gt;Always fresh&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache in Redis (in-memory)&lt;/td&gt;
&lt;td&gt;Memory cost (~$0.01/GB-hr)&lt;/td&gt;
&lt;td&gt;~1ms&lt;/td&gt;
&lt;td&gt;Stale by TTL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache at CDN edge&lt;/td&gt;
&lt;td&gt;Bandwidth cost&lt;/td&gt;
&lt;td&gt;~5ms&lt;/td&gt;
&lt;td&gt;Stale by TTL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pre-compute &amp;amp; store&lt;/td&gt;
&lt;td&gt;Storage cost&lt;/td&gt;
&lt;td&gt;~1ms&lt;/td&gt;
&lt;td&gt;Stale until recompute&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Rule of thumb:&lt;/strong&gt; If the same data is read 100x more than it's written → cache it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Read Replicas vs Scaling Primary
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Adding read replicas: cheaper than scaling the primary&lt;/li&gt;
&lt;li&gt;Primary is the bottleneck for writes; replicas handle reads&lt;/li&gt;
&lt;li&gt;Cost: 1 primary ($200/mo) + 2 replicas ($100/mo each) vs 1 massive primary ($600/mo)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📦 Storage Tiering
&lt;/h2&gt;

&lt;p&gt;Not all data needs to be fast. Match storage speed to access frequency:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;Technology&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;th&gt;Access Time&lt;/th&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Hot&lt;/td&gt;
&lt;td&gt;SSD / NVMe&lt;/td&gt;
&lt;td&gt;$$$&lt;/td&gt;
&lt;td&gt;&amp;lt; 1ms&lt;/td&gt;
&lt;td&gt;Active user data, recent records&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Warm&lt;/td&gt;
&lt;td&gt;HDD / Standard S3&lt;/td&gt;
&lt;td&gt;$$&lt;/td&gt;
&lt;td&gt;10–100ms&lt;/td&gt;
&lt;td&gt;Last 90 days of logs, old orders&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cold&lt;/td&gt;
&lt;td&gt;S3-IA, Glacier&lt;/td&gt;
&lt;td&gt;$&lt;/td&gt;
&lt;td&gt;Minutes–hours&lt;/td&gt;
&lt;td&gt;Compliance archives, old backups&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Archive&lt;/td&gt;
&lt;td&gt;Glacier Deep Archive&lt;/td&gt;
&lt;td&gt;¢&lt;/td&gt;
&lt;td&gt;12–48 hours&lt;/td&gt;
&lt;td&gt;Legal hold, never-accessed data&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Interview tip:&lt;/strong&gt; Propose tiering when the interviewer mentions "we have 10 years of data." Storing all of it on SSD is wasteful — tier it.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ Instance Right-Sizing
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Over-provisioning&lt;/strong&gt; = money wasted on idle CPU/RAM&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Under-provisioning&lt;/strong&gt; = throttling, poor UX&lt;/li&gt;
&lt;li&gt;Tools: AWS Cost Explorer, GCP Recommender, CloudWatch metrics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Spot / Preemptible Instances&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Up to 90% cheaper than on-demand&lt;/li&gt;
&lt;li&gt;Can be reclaimed by cloud provider with 2-minute notice&lt;/li&gt;
&lt;li&gt;✅ Use for: batch jobs, ML training, stateless workers&lt;/li&gt;
&lt;li&gt;❌ Don't use for: databases, stateful services, API servers&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🗄️ Database Cost Tricks
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Trick&lt;/th&gt;
&lt;th&gt;Saving&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Use read replicas for analytics queries&lt;/td&gt;
&lt;td&gt;Don't tax primary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Partition old data to cheap storage&lt;/td&gt;
&lt;td&gt;$$$→$ for cold rows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use DynamoDB On-Demand for spiky, low-volume traffic&lt;/td&gt;
&lt;td&gt;Pay per request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use Aurora Serverless for dev/staging DBs&lt;/td&gt;
&lt;td&gt;0 cost when idle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Index correctly&lt;/td&gt;
&lt;td&gt;Avoid full table scans = less I/O cost&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🌐 CDN vs Origin Cost
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Without CDN:&lt;/strong&gt; Every request hits your servers (compute + bandwidth cost)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;With CDN:&lt;/strong&gt; Cache hit ratio of 80%+ means 80% less origin load&lt;/li&gt;
&lt;li&gt;CDN bandwidth: ~$0.01/GB vs EC2 egress: ~$0.09/GB → 9x cheaper&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔁 Async Processing to Cut Peak Compute
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Synchronous: request waits → need enough servers for PEAK traffic&lt;/li&gt;
&lt;li&gt;Async + queue: requests enqueue → process at steady rate → smaller fleet&lt;/li&gt;
&lt;li&gt;Example: Image processing. 1000 uploads/minute at peak.

&lt;ul&gt;
&lt;li&gt;Sync: need 1000 workers provisioned at all times&lt;/li&gt;
&lt;li&gt;Async + SQS: 50 workers process queue, backlog drains within minutes&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚖️ Trade-offs
&lt;/h2&gt;

&lt;p&gt;✅ &lt;strong&gt;Pros of cost optimization&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lower burn rate (critical at startups)&lt;/li&gt;
&lt;li&gt;Forces engineering discipline&lt;/li&gt;
&lt;li&gt;Scales better — inefficiencies compound at scale&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❌ &lt;strong&gt;Cons / Risks&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Over-optimizing early wastes engineering time&lt;/li&gt;
&lt;li&gt;Spot instances add operational complexity&lt;/li&gt;
&lt;li&gt;Storage tiering adds retrieval latency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚖️ &lt;strong&gt;When to bring this up in interviews&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When asked about scaling to millions of users&lt;/li&gt;
&lt;li&gt;When interviewer asks "what else would you consider?"&lt;/li&gt;
&lt;li&gt;When discussing database choices (cost of managed vs self-hosted)&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>systemdesign</category>
      <category>distributedsystems</category>
    </item>
    <item>
      <title>Multi-Region &amp; Geo-Distribution</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Sun, 27 Sep 2026 04:00:00 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/multi-region-geo-distribution-2mjl</link>
      <guid>https://dev.to/gouranga-das-khulna/multi-region-geo-distribution-2mjl</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Senior-level signal 💯 — most candidates skip this entirely. Knowing this separates you.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Why Multi-Region?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Reason&lt;/th&gt;
&lt;th&gt;Explanation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Latency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Serve users from the nearest region (100ms vs 400ms)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Availability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;One region down ≠ whole system down&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Compliance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GDPR, data residency laws (EU data must stay in EU)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Disaster Recovery&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Survive regional cloud outages (AWS us-east-1 has gone down)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🗺️ Deployment Models
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Active-Passive
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;One region handles ALL traffic&lt;/li&gt;
&lt;li&gt;Passive region is on standby (warm or cold)&lt;/li&gt;
&lt;li&gt;Failover takes time (seconds to minutes)&lt;/li&gt;
&lt;li&gt;✅ Simpler, cheaper&lt;/li&gt;
&lt;li&gt;❌ Wasted capacity, failover downtime&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Active-Active
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Multiple regions ALL handle traffic simultaneously&lt;/li&gt;
&lt;li&gt;Load balanced across regions&lt;/li&gt;
&lt;li&gt;✅ Full utilization, instant failover&lt;/li&gt;
&lt;li&gt;❌ Data consistency is HARD (writes to two regions = conflict risk)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔄 Data Replication Across Regions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Synchronous Replication
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Write confirms only after all replicas ACK&lt;/li&gt;
&lt;li&gt;✅ Zero data loss&lt;/li&gt;
&lt;li&gt;❌ High latency (write waits for far region)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Asynchronous Replication
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Write confirms after primary writes; replicas catch up&lt;/li&gt;
&lt;li&gt;✅ Low write latency&lt;/li&gt;
&lt;li&gt;❌ Replication lag — RPO &amp;gt; 0 (can lose recent writes on failover)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conflict Resolution (Active-Active)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Last Write Wins (LWW)&lt;/strong&gt; — timestamp determines winner (risk: clock skew)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vector Clocks&lt;/strong&gt; — track causality, not just time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CRDTs&lt;/strong&gt; — data structures that merge automatically (counters, sets)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application-level&lt;/strong&gt; — humans or business logic resolves conflicts&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧭 Latency-Based Routing
&lt;/h2&gt;

&lt;p&gt;Route users to the nearest healthy region:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User in London → EU-WEST region
User in Singapore → AP-SOUTHEAST region
User in NYC → US-EAST region
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DNS-level routing (Route 53 latency routing, Cloudflare)&lt;/li&gt;
&lt;li&gt;Measures latency from user to each region endpoint&lt;/li&gt;
&lt;li&gt;Routes to lowest-latency region&lt;/li&gt;
&lt;li&gt;Falls back to next region if primary is unhealthy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Other routing strategies:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Geolocation routing&lt;/strong&gt; — by country/continent (compliance use case)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Weighted routing&lt;/strong&gt; — 90% to main region, 10% to new region (blue/green)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Failover routing&lt;/strong&gt; — primary + health check → failover on failure&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💥 Disaster Recovery Concepts
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Term&lt;/th&gt;
&lt;th&gt;Definition&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RTO&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Recovery Time Objective — how long can system be down?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RPO&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Recovery Point Objective — how much data can we lose?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Failover&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Switch traffic to backup region&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Failback&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Return to primary after recovery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Runbook&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Step-by-step incident playbook&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  DR Tiers
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;RTO&lt;/th&gt;
&lt;th&gt;RPO&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;th&gt;Strategy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cold Standby&lt;/td&gt;
&lt;td&gt;Hours&lt;/td&gt;
&lt;td&gt;Hours&lt;/td&gt;
&lt;td&gt;$&lt;/td&gt;
&lt;td&gt;Data backed up, infra off&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Warm Standby&lt;/td&gt;
&lt;td&gt;Minutes&lt;/td&gt;
&lt;td&gt;Minutes&lt;/td&gt;
&lt;td&gt;$$&lt;/td&gt;
&lt;td&gt;Infra running, minimal traffic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hot Standby&lt;/td&gt;
&lt;td&gt;Seconds&lt;/td&gt;
&lt;td&gt;Seconds&lt;/td&gt;
&lt;td&gt;$$$&lt;/td&gt;
&lt;td&gt;Full mirror, active-active&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  ⚖️ Trade-offs
&lt;/h2&gt;

&lt;p&gt;✅ &lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sub-100ms latency for global users&lt;/li&gt;
&lt;li&gt;Survives regional cloud outages&lt;/li&gt;
&lt;li&gt;Compliance with data residency laws&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❌ &lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data consistency is fundamentally harder&lt;/li&gt;
&lt;li&gt;Cost multiplier (2x–3x infrastructure)&lt;/li&gt;
&lt;li&gt;Operational complexity (multi-region debugging, data sync issues)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚖️ &lt;strong&gt;When to use&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Global user base (users in 3+ continents)&lt;/li&gt;
&lt;li&gt;SLAs requiring 99.99%+ uptime&lt;/li&gt;
&lt;li&gt;Revenue impact of downtime &amp;gt; cost of multi-region&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When NOT to use&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Small startup with users in one country&lt;/li&gt;
&lt;li&gt;Early stage — single-region with good backups is fine&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>systemdesign</category>
      <category>distributedsystems</category>
      <category>backend</category>
      <category>devops</category>
    </item>
    <item>
      <title>Service Discovery</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Sat, 26 Sep 2026 04:00:00 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/service-discovery-4f16</link>
      <guid>https://dev.to/gouranga-das-khulna/service-discovery-4f16</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;One-liner:&lt;/strong&gt; Service discovery is how microservices find each other at runtime — instead of hardcoding IP addresses, services register themselves and clients look them up dynamically.&lt;/p&gt;
&lt;/blockquote&gt;




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

&lt;p&gt;In microservices, services run on dynamic infrastructure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Container IPs change on every restart&lt;/li&gt;
&lt;li&gt;Services scale up/down constantly&lt;/li&gt;
&lt;li&gt;Multiple instances run behind a load balancer&lt;/li&gt;
&lt;li&gt;New versions deploy and old ones disappear&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Hardcoding IPs breaks instantly.&lt;/strong&gt; You need a phone book that updates itself.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏗️ Two Patterns
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Client-Side Discovery
&lt;/h3&gt;

&lt;p&gt;The client asks a &lt;strong&gt;Service Registry&lt;/strong&gt; directly, then calls the service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client  ──► Registry: "Where is payment-service?"
        ◄── Registry: "192.168.1.5:3001, 192.168.1.6:3001"
Client  ──► payment-service:3001 (client picks one, does LB itself)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Tools:&lt;/strong&gt; Eureka (Netflix), Consul&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Client controls load balancing logic&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; Client must have discovery library for every language&lt;/p&gt;


&lt;h3&gt;
  
  
  2. Server-Side Discovery
&lt;/h3&gt;

&lt;p&gt;The client calls a &lt;strong&gt;Load Balancer / API Gateway&lt;/strong&gt;, which does the lookup.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client  ──► Load Balancer: "POST /payments"
LB      ──► Registry: "Where is payment-service?"
        ◄── Registry: "192.168.1.5:3001"
LB      ──► payment-service:3001
        ◄── Response
Client  ◄── Response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Tools:&lt;/strong&gt; AWS ALB + ECS, Kubernetes, Nginx + Consul&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Client is dumb (no discovery code needed)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; Extra hop, LB is a potential bottleneck&lt;/p&gt;


&lt;h2&gt;
  
  
  📋 Service Registry
&lt;/h2&gt;

&lt;p&gt;The central database of "who's alive and where."&lt;/p&gt;
&lt;h3&gt;
  
  
  Registration (how services join)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Self-registration:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;service&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;registers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;itself&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;startup&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;POST&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;/v&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;/agent/service/register&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;span class="nl"&gt;"Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"payment-service"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"payment-service-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"192.168.1.5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Check"&lt;/span&gt;&lt;span class="p"&gt;:&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;span class="nl"&gt;"HTTP"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://192.168.1.5:3001/health"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Interval"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10s"&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;←&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;health&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;check&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;every&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;seconds&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;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Third-party&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;registration:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;orchestrator&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;registers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(Kubernetes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;does&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;this)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Health Checks
&lt;/h3&gt;

&lt;p&gt;Registry pings each registered service. If it fails N times → marked unhealthy → removed from discovery results.&lt;/p&gt;


&lt;h2&gt;
  
  
  🔧 Tools Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Consul&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Client-side + KV store&lt;/td&gt;
&lt;td&gt;Multi-DC, service mesh&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Eureka&lt;/strong&gt; (Netflix)&lt;/td&gt;
&lt;td&gt;Client-side&lt;/td&gt;
&lt;td&gt;Spring Boot microservices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;etcd&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Key-value + watch&lt;/td&gt;
&lt;td&gt;Kubernetes backbone&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Kubernetes DNS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Server-side&lt;/td&gt;
&lt;td&gt;K8s native (just use it)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AWS Cloud Map&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Server-side&lt;/td&gt;
&lt;td&gt;AWS ECS/EKS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Zookeeper&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Client-side&lt;/td&gt;
&lt;td&gt;Older Kafka setups&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Kubernetes DNS (simplest)
&lt;/h3&gt;

&lt;p&gt;In K8s, services get a DNS name automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;payment-service.default.svc.cluster.local
&lt;span class="c"&gt;# format: &amp;lt;service-name&amp;gt;.&amp;lt;namespace&amp;gt;.svc.cluster.local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just call &lt;code&gt;http://payment-service/pay&lt;/code&gt; — K8s handles the rest.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Pros
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;No hardcoded IPs — services survive restarts and scaling&lt;/li&gt;
&lt;li&gt;Automatic health check integration&lt;/li&gt;
&lt;li&gt;Enables zero-downtime deployments&lt;/li&gt;
&lt;li&gt;Foundation for service mesh (Istio, Linkerd)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ❌ Cons
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Registry itself is a single point of failure (needs HA)&lt;/li&gt;
&lt;li&gt;Adds operational complexity&lt;/li&gt;
&lt;li&gt;Stale entries possible if TTL/health checks are misconfigured&lt;/li&gt;
&lt;li&gt;Client-side pattern requires polyglot library support&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ⚖️ When to Use / When NOT to Use
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;✅ Use when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Running 5+ microservices that need to communicate&lt;/li&gt;
&lt;li&gt;Containers restart with changing IPs&lt;/li&gt;
&lt;li&gt;Auto-scaling groups where instance count changes&lt;/li&gt;
&lt;li&gt;Multi-region deployments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;❌ Avoid / not needed when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Monolith or 2-3 services with stable IPs&lt;/li&gt;
&lt;li&gt;Already on Kubernetes (use built-in DNS — no extra tool needed)&lt;/li&gt;
&lt;li&gt;Services communicate only through a message queue (no direct calls)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>systemdesign</category>
      <category>distributedsystems</category>
      <category>backend</category>
    </item>
    <item>
      <title>Observability — Logs, Metrics, Tracing</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Sun, 20 Sep 2026 04:00:00 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/observability-logs-metrics-tracing-2k8c</link>
      <guid>https://dev.to/gouranga-das-khulna/observability-logs-metrics-tracing-2k8c</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;One-liner:&lt;/strong&gt; Observability is your ability to understand what's happening inside your system from the outside — the three pillars are logs, metrics, and distributed traces.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🏛️ The Three Pillars
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌──────────────────────────────────────────────────────────────┐
│                       OBSERVABILITY                          │
│                                                              │
│  📋 LOGS          📊 METRICS           🔗 TRACES             │
│  "What happened"  "How is it doing"    "Where did time go"   │
│  Events, errors   Numbers over time    Request journey        │
└──────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📋 Pillar 1: Logs
&lt;/h2&gt;

&lt;p&gt;Timestamped records of discrete events.&lt;/p&gt;

&lt;h3&gt;
  
  
  Structured Logging (JSON — do this, not plain text)
&lt;/h3&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;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-03-15T10:23:45Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ERROR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"payment-service"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"traceId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"abc-123-xyz"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"userId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Payment declined"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"INSUFFICIENT_FUNDS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;99.99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"durationMs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;342&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;&lt;strong&gt;Why structured?&lt;/strong&gt; You can filter, aggregate, and alert on specific fields. &lt;code&gt;grep&lt;/code&gt; on plain text doesn't scale to millions of log lines.&lt;/p&gt;

&lt;h3&gt;
  
  
  Log Levels
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Level&lt;/th&gt;
&lt;th&gt;When to Use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DEBUG&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Dev only — verbose, turned off in prod&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;INFO&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Normal operations, key business events&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;WARN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Unexpected but handled (retry succeeded)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ERROR&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Something failed, needs attention&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;FATAL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Service cannot continue, immediate alert&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Log Aggregation Stack
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Services → Fluentd/Logstash → Elasticsearch → Kibana (ELK)
                           or
Services → CloudWatch Logs (AWS) → CloudWatch Insights
Services → Loki → Grafana (cheaper, label-based)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📊 Pillar 2: Metrics
&lt;/h2&gt;

&lt;p&gt;Numerical measurements aggregated over time.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Four Golden Signals (Google SRE)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;What It Measures&lt;/th&gt;
&lt;th&gt;Example Alert&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Latency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;How long requests take&lt;/td&gt;
&lt;td&gt;p99 &amp;gt; 500ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Traffic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;How much demand&lt;/td&gt;
&lt;td&gt;RPS spike &amp;gt;2x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Errors&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Rate of failures&lt;/td&gt;
&lt;td&gt;Error rate &amp;gt; 1%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Saturation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;How full is the system&lt;/td&gt;
&lt;td&gt;CPU &amp;gt; 80%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Key Metrics to Track
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight prometheus"&gt;&lt;code&gt;&lt;span class="c"&gt;# Business&lt;/span&gt;
&lt;span class="o"&gt;or&lt;/span&gt;&lt;span class="n"&gt;ders_per_minute&lt;/span&gt;
&lt;span class="n"&gt;revenue_per_hour&lt;/span&gt;
&lt;span class="n"&gt;active_users&lt;/span&gt;

&lt;span class="c"&gt;# Infrastructure&lt;/span&gt;
&lt;span class="n"&gt;http_request_duration_seconds&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;histogram&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;http_requests_total&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"500"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;db_connection_pool_used&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gauge&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cache_hit_rate&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gauge&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;message_queue_depth&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gauge&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Metrics Stack
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Services → Prometheus (pull-based scraping) → Grafana (dashboards)
                                           → AlertManager (alerts)

OR: Datadog, New Relic, CloudWatch Metrics (SaaS, easier ops)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔗 Pillar 3: Distributed Tracing
&lt;/h2&gt;

&lt;p&gt;Follow a single request across multiple services.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem Without Tracing
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User: "The checkout is slow"
You:  Is it the API gateway? Auth service? Cart service?
      Payment service? DB? Which hop is slow? No idea. 😰
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  With Tracing
&lt;/h3&gt;



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

API Gateway      ████ 5ms
  └─ Auth        ████ 12ms
  └─ Cart        ████████████ 250ms  ← bottleneck!
       └─ DB     █████████ 220ms    ← query too slow
  └─ Payment     ████ 8ms

Total: 275ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Middleware auto-injects trace context&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;traceId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x-trace-id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nf"&gt;generateId&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;spanId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateId&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Pass downstream in headers:&lt;/span&gt;
  &lt;span class="c1"&gt;// x-trace-id: abc-123&lt;/span&gt;
  &lt;span class="c1"&gt;// x-parent-span-id: span-456&lt;/span&gt;
  &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;traceContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;traceId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;spanId&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nf"&gt;next&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;h3&gt;
  
  
  Tracing Tools
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Jaeger&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Open source&lt;/td&gt;
&lt;td&gt;Kubernetes, self-hosted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Zipkin&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Open source&lt;/td&gt;
&lt;td&gt;Simpler setup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AWS X-Ray&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Managed&lt;/td&gt;
&lt;td&gt;AWS native workloads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Datadog APM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SaaS&lt;/td&gt;
&lt;td&gt;Full observability suite&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OpenTelemetry&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Standard&lt;/td&gt;
&lt;td&gt;Vendor-neutral instrumentation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;OpenTelemetry&lt;/strong&gt; is the industry standard for instrumentation — use it and swap backends freely.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔔 Alerting Strategy
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tier 1 (Page immediately):  p99 latency &amp;gt; 2s for 5 min
                            Error rate &amp;gt; 5%
                            Service down

Tier 2 (Slack/ticket):      Error rate &amp;gt; 1%
                            p99 &amp;gt; 500ms
                            DB connections &amp;gt; 80%

Tier 3 (Weekly review):     Slow trend upward
                            Disk usage &amp;gt; 70%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Alert on symptoms, not causes.&lt;/strong&gt; Alert on "error rate high", not "CPU high" — users don't care about CPU.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Pros
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Find bugs and incidents fast (MTTR reduction)&lt;/li&gt;
&lt;li&gt;Capacity planning from metrics trends&lt;/li&gt;
&lt;li&gt;Proves SLA compliance with data&lt;/li&gt;
&lt;li&gt;Tracing reveals hidden performance bottlenecks&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ❌ Cons
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Adds cost: storage for logs and metrics, SaaS fees&lt;/li&gt;
&lt;li&gt;Cardinality explosion in metrics (too many label combinations)&lt;/li&gt;
&lt;li&gt;Log volume can be enormous at scale (sampling helps)&lt;/li&gt;
&lt;li&gt;Requires cultural buy-in — teams must actually look at dashboards&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ⚖️ When to Use / When NOT to Use
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;✅ Use when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Any production system (non-negotiable at scale)&lt;/li&gt;
&lt;li&gt;Microservices where request paths cross multiple services&lt;/li&gt;
&lt;li&gt;SLA commitments requiring uptime/latency guarantees&lt;/li&gt;
&lt;li&gt;Debugging production incidents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;❌ Skip the complexity when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Early prototype / dev environment&lt;/li&gt;
&lt;li&gt;Single-service monolith with few users (basic logging is fine)&lt;/li&gt;
&lt;li&gt;Cost is the primary constraint (use sampling + retention policies)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>systemdesign</category>
      <category>distributedsystems</category>
      <category>security</category>
      <category>backend</category>
    </item>
    <item>
      <title>Idempotency</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Sat, 19 Sep 2026 04:00:00 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/idempotency-3g2d</link>
      <guid>https://dev.to/gouranga-das-khulna/idempotency-3g2d</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;One-liner:&lt;/strong&gt; An operation is idempotent if doing it multiple times produces the same result as doing it once — critical for safe retries in distributed systems.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  ❓ Why Does This Matter?
&lt;/h2&gt;

&lt;p&gt;In distributed systems, &lt;strong&gt;anything can fail at any time&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Network times out — did the server receive the request?&lt;/li&gt;
&lt;li&gt;Client retries — does the server process it again?&lt;/li&gt;
&lt;li&gt;Message queue delivers a message twice&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Without idempotency:&lt;/strong&gt; User clicks "Pay" → network blips → client retries → user charged twice. 💸&lt;/p&gt;




&lt;h2&gt;
  
  
  📐 Idempotent vs Non-Idempotent
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Idempotent?&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET /users/1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;Same response every time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PUT /users/1 {name: "Ali"}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;Setting to same value&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DELETE /users/1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;Second delete = already gone&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;POST /payments {amount: 100}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;Creates a new charge each time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PATCH /account/balance -=100&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;Each call subtracts again&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🔑 Idempotency Keys
&lt;/h2&gt;

&lt;p&gt;The standard solution for non-idempotent operations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Client generates:  idempotency-key: uuid-abc-123

POST /payments
Headers:
  Idempotency-Key: uuid-abc-123
Body:
  { amount: 100, currency: "USD" }
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Server logic:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Receive request with idempotency-key
2. Check: have we seen this key before?
   NO  → Process payment, store result with key (TTL: 24h)
   YES → Return cached response (don't charge again)
3. Return result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Storage example (Redis):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# On first request:&lt;/span&gt;
SET idem:uuid-abc-123 &lt;span class="s1"&gt;'{"status":"ok","chargeId":"ch_123"}'&lt;/span&gt; EX 86400

&lt;span class="c"&gt;# On retry:&lt;/span&gt;
GET idem:uuid-abc-123  &lt;span class="c"&gt;# Returns cached response immediately&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🏗️ Database-Level Idempotency
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Unique Constraints
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Prevent duplicate order creation&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;UUID&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;idempotency_key&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;255&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="c1"&gt;-- ← key here&lt;/span&gt;
  &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="nb"&gt;DECIMAL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="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="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;idempotency_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gen_random_uuid&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s1"&gt;'uuid-abc-123'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;CONFLICT&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;idempotency_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;DO&lt;/span&gt; &lt;span class="k"&gt;NOTHING&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;--                                         ↑ safe retry!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conditional Updates (Optimistic Locking)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;version&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="k"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- If version changed, 0 rows updated → retry with fresh data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔄 Idempotency in Message Queues
&lt;/h2&gt;

&lt;p&gt;SQS, Kafka — delivery guarantees are &lt;strong&gt;at-least-once&lt;/strong&gt;. Your consumers must be idempotent.&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;processPaymentEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;paymentId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Check if already processed&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;exists&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;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT 1 FROM processed_payments WHERE payment_id = $1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;paymentId&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Already done, skip&lt;/span&gt;

  &lt;span class="c1"&gt;// Process payment&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;chargeUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Mark as processed&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;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;INSERT INTO processed_payments (payment_id) VALUES ($1)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;paymentId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ✅ Pros
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Safe retries without side effects&lt;/li&gt;
&lt;li&gt;Enables reliable distributed workflows&lt;/li&gt;
&lt;li&gt;Standard Stripe/PayPal/Twilio all use idempotency keys&lt;/li&gt;
&lt;li&gt;Works naturally with at-least-once delivery&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ❌ Cons
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Extra storage needed for idempotency key cache&lt;/li&gt;
&lt;li&gt;Key management adds complexity (TTL choices, cleanup)&lt;/li&gt;
&lt;li&gt;Doesn't help if operations must be strictly ordered&lt;/li&gt;
&lt;li&gt;Race condition: two parallel requests with same key can both pass check simultaneously → need atomic check-and-set&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ⚖️ When to Use / When NOT to Use
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;✅ Use when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Payment processing, order creation (any financial operation)&lt;/li&gt;
&lt;li&gt;Email/SMS sending (prevent duplicates)&lt;/li&gt;
&lt;li&gt;Message queue consumers (at-least-once delivery)&lt;/li&gt;
&lt;li&gt;Any API that clients will retry on failure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;❌ Avoid / not needed when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pure reads (already idempotent by nature)&lt;/li&gt;
&lt;li&gt;Strictly ordered append-only logs&lt;/li&gt;
&lt;li&gt;Operations where duplicates are intentional (e.g., add to cart)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>systemdesign</category>
      <category>distributedsystems</category>
      <category>security</category>
    </item>
    <item>
      <title>Distributed Locks</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Sun, 13 Sep 2026 04:00:00 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/distributed-locks-4148</link>
      <guid>https://dev.to/gouranga-das-khulna/distributed-locks-4148</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;One-liner:&lt;/strong&gt; A distributed lock ensures that only one node in a cluster can perform a critical operation at a time — preventing race conditions across services.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  ❓ Why Do You Need Distributed Locks?
&lt;/h2&gt;

&lt;p&gt;In a single-server world, a mutex or semaphore handles concurrency. But in distributed systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple service replicas run simultaneously&lt;/li&gt;
&lt;li&gt;They all share the same database or resource&lt;/li&gt;
&lt;li&gt;Without coordination, two instances might process the same job, double-charge a user, or corrupt shared state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Classic example:&lt;/strong&gt; Flash sale — 100 units in stock, 10,000 concurrent requests. Without a lock, you oversell.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔑 Redis Distributed Lock (Redlock)
&lt;/h2&gt;

&lt;p&gt;The most common approach: use Redis &lt;code&gt;SET NX EX&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Acquire lock&lt;/span&gt;
SET lock:resource_id &amp;lt;unique_token&amp;gt; NX EX 10
&lt;span class="c"&gt;# NX = only set if key does NOT exist&lt;/span&gt;
&lt;span class="c"&gt;# EX 10 = auto-expire in 10 seconds (TTL safety net)&lt;/span&gt;

&lt;span class="c"&gt;# Returns OK → you have the lock&lt;/span&gt;
&lt;span class="c"&gt;# Returns nil → someone else has it&lt;/span&gt;

&lt;span class="c"&gt;# Release lock (Lua script — atomic!)&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;redis.call&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"GET"&lt;/span&gt;, KEYS[1]&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; ARGV[1] &lt;span class="k"&gt;then
  return &lt;/span&gt;redis.call&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"DEL"&lt;/span&gt;, KEYS[1]&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else
  return &lt;/span&gt;0
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why a unique token?&lt;/strong&gt; Prevents a slow process from releasing a lock that was already acquired by someone else after TTL expiry.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ How It Works (Step by Step)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Service A                    Redis                   Service B
   |                           |                        |
   |── SET lock:job1 tokenA ──&amp;gt;|                        |
   |   NX EX 10                |                        |
   |&amp;lt;── OK (lock acquired) ────|                        |
   |                           |                        |
   |   (doing work...)         |── SET lock:job1 ──────&amp;gt;|
   |                           |   tokenB NX EX 10      |
   |                           |&amp;lt;── nil (locked) ───────|
   |                           |   (retry or fail)      |
   |                           |                        |
   |── DEL lock:job1 ─────────&amp;gt;|                        |
   |   (if token matches)      |                        |
   |&amp;lt;── lock released ─────────|                        |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⚠️ Edge Cases &amp;amp; Gotchas
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;What Happens&lt;/th&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Process crashes&lt;/td&gt;
&lt;td&gt;Lock stuck forever&lt;/td&gt;
&lt;td&gt;TTL auto-expire&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network partition&lt;/td&gt;
&lt;td&gt;Two leaders think they have lock&lt;/td&gt;
&lt;td&gt;Redlock (multi-node)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GC pause longer than TTL&lt;/td&gt;
&lt;td&gt;Process resumes, lock already expired&lt;/td&gt;
&lt;td&gt;Fencing tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Redis crashes&lt;/td&gt;
&lt;td&gt;Lock lost&lt;/td&gt;
&lt;td&gt;Use Redis Cluster / persistence&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Fencing Token Pattern
&lt;/h3&gt;

&lt;p&gt;Each lock acquisition returns a monotonically increasing token number. The resource (e.g., DB) only accepts writes with tokens higher than the last seen:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Lock acquired → token 42
Lock expired, re-acquired → token 43
Stale process tries to write with token 42 → REJECTED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🏛️ Alternatives to Redis Locks
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Mechanism&lt;/th&gt;
&lt;th&gt;Use When&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Redis (SET NX)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Atomic key-value&lt;/td&gt;
&lt;td&gt;Most common, low latency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ZooKeeper&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ephemeral nodes + watchers&lt;/td&gt;
&lt;td&gt;Need strong consistency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;etcd&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Leases + CAS&lt;/td&gt;
&lt;td&gt;Kubernetes-style infra&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DB row lock&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT FOR UPDATE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Already using SQL, low scale&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  ✅ Pros
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Sub-millisecond lock acquisition with Redis&lt;/li&gt;
&lt;li&gt;TTL prevents deadlocks from crashed processes&lt;/li&gt;
&lt;li&gt;Simple to implement with &lt;code&gt;SET NX EX&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Scales with Redis Cluster&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ❌ Cons
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Redis is single point of failure (use Redlock for HA)&lt;/li&gt;
&lt;li&gt;Clock drift can cause issues with TTL-based expiry&lt;/li&gt;
&lt;li&gt;Redlock is controversial (Martin Kleppmann vs. Antirez debate)&lt;/li&gt;
&lt;li&gt;Not suitable for long-held locks (use queue instead)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ⚖️ When to Use / When NOT to Use
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;✅ Use when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Preventing double processing (payment, job scheduling)&lt;/li&gt;
&lt;li&gt;Flash sales / inventory deduction&lt;/li&gt;
&lt;li&gt;Leader election among service instances&lt;/li&gt;
&lt;li&gt;Rate limiting per resource&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;❌ Avoid when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Operations take longer than a reasonable TTL (use idempotency + queue instead)&lt;/li&gt;
&lt;li&gt;You need guaranteed strong consistency (use ZooKeeper + fencing)&lt;/li&gt;
&lt;li&gt;The resource is already serialized (single-threaded queue consumer)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>systemdesign</category>
      <category>distributedsystems</category>
      <category>backend</category>
      <category>security</category>
    </item>
    <item>
      <title>Circuit Breaker Pattern</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Sat, 12 Sep 2026 04:00:00 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/circuit-breaker-pattern-39op</link>
      <guid>https://dev.to/gouranga-das-khulna/circuit-breaker-pattern-39op</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;One-liner:&lt;/strong&gt; A circuit breaker stops calling a failing service to give it time to recover — instead of hammering it with requests that are guaranteed to fail.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  ❓ The Problem: Cascading Failures
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Request
    ↓
Service A  ──► Service B  ──► Service C (DOWN 💥)
    ↑              ↑
Threads hang   Threads hang
(timeout 30s)  (timeout 30s)

→ Service A's thread pool exhausts
→ Service A goes down
→ Everything upstream dies
→ Full cascade failure 🔥
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without circuit breakers, &lt;strong&gt;one slow service kills your entire system&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔌 The Three States
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────┐
│                      CLOSED                             │
│              (Normal operation)                         │
│   Requests flow through. Track failure rate.            │
│   Failure threshold exceeded → trip to OPEN             │
└──────────────────────────┬──────────────────────────────┘
                           │ failures &amp;gt; threshold
                           ▼
┌─────────────────────────────────────────────────────────┐
│                       OPEN                              │
│              (Service is DOWN)                          │
│   All requests IMMEDIATELY fail (no network call)       │
│   Return cached/default response                        │
│   Wait for reset timeout (e.g., 60s) → HALF-OPEN       │
└──────────────────────────┬──────────────────────────────┘
                           │ timeout elapsed
                           ▼
┌─────────────────────────────────────────────────────────┐
│                    HALF-OPEN                            │
│              (Testing recovery)                         │
│   Let a few probe requests through                      │
│   Success → CLOSED (recovered! ✅)                      │
│   Failure → back to OPEN (still down ❌)                │
└─────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  💻 Implementation Example (Conceptual)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CircuitBreaker&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;failureThreshold&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resetTimeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;60000&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CLOSED&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;failureCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;failureThreshold&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;failureThreshold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resetTimeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resetTimeout&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OPEN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Fail fast — don't even try&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;try&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onFailure&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;failureCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CLOSED&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;onFailure&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;failureCount&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;failureCount&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;failureThreshold&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OPEN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;HALF_OPEN&lt;/span&gt;&lt;span class="dl"&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resetTimeout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Service temporarily unavailable&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;cached&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paymentBreaker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CircuitBreaker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callPaymentService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;failureThreshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;resetTimeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30000&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;h2&gt;
  
  
  🛠️ Production Libraries
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;Library&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Java&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Resilience4j&lt;/strong&gt;, Hystrix (deprecated)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;opossum&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;sony/gobreaker&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;pybreaker&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.NET&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Polly&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Service mesh&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Istio&lt;/strong&gt; (no code changes needed)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🔗 Circuit Breaker + Fallback Strategies
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Fallback Type&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cached response&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Return last known good data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Default value&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Show "0 recommendations" instead of error&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Static response&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Return empty array, blank page&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Redirect&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Send to static maintenance page&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Queue&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Accept request, process later&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  ✅ Pros
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prevents cascading failures — protects the whole system&lt;/li&gt;
&lt;li&gt;Fail-fast gives users a quick response instead of 30s timeout&lt;/li&gt;
&lt;li&gt;Gives the failing service breathing room to recover&lt;/li&gt;
&lt;li&gt;Enables graceful degradation with fallbacks&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ❌ Cons
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Adds complexity to every service call&lt;/li&gt;
&lt;li&gt;Threshold tuning is tricky (too sensitive = flapping, too lax = slow to trip)&lt;/li&gt;
&lt;li&gt;Half-open probes can still let some failures through&lt;/li&gt;
&lt;li&gt;Stale cached data shown as fallback may mislead users&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ⚖️ When to Use / When NOT to Use
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;✅ Use when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Calling external APIs or microservices (anything that can fail)&lt;/li&gt;
&lt;li&gt;Third-party integrations (payment gateways, SMS providers)&lt;/li&gt;
&lt;li&gt;Inter-service communication in microservices architecture&lt;/li&gt;
&lt;li&gt;Any synchronous call that has a timeout risk&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;❌ Avoid when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Calling a local in-process function (no network, no need)&lt;/li&gt;
&lt;li&gt;Using async message queues (they decouple naturally)&lt;/li&gt;
&lt;li&gt;Already using a service mesh like Istio (it handles this for you)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>security</category>
      <category>systemdesign</category>
      <category>distributedsystems</category>
    </item>
  </channel>
</rss>
