<?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: Joud Awad</title>
    <description>The latest articles on DEV Community by Joud Awad (@thejoud1997).</description>
    <link>https://dev.to/thejoud1997</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%2F1238326%2F5d65a5d6-611d-4526-9bc2-d2d8643d5226.png</url>
      <title>DEV Community: Joud Awad</title>
      <link>https://dev.to/thejoud1997</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thejoud1997"/>
    <language>en</language>
    <item>
      <title>Event-Driven Architecture Full Course: Beginner to Advanced</title>
      <dc:creator>Joud Awad</dc:creator>
      <pubDate>Mon, 12 Oct 2026 15:01:31 +0000</pubDate>
      <link>https://dev.to/thejoud1997/event-driven-architecture-full-course-beginner-to-advanced-37mc</link>
      <guid>https://dev.to/thejoud1997/event-driven-architecture-full-course-beginner-to-advanced-37mc</guid>
      <description>&lt;p&gt;Everyone draws event-driven architecture the same way. Three boxes: producer, broker, consumer.&lt;/p&gt;

&lt;p&gt;That drawing hides almost every decision that comes back to bite you.&lt;/p&gt;

&lt;p&gt;Start with the producer. Is it publishing an event or a command? Both end up in the same broker, so a lot of teams treat them the same.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An event is a fact that already happened. "VideoUploaded." The producer has no idea who's listening, and it shouldn't.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A command is a request. "TranscodeVideo." It has one intended handler, and that handler is allowed to say no.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Blur the two and you get a system that looks decoupled on the diagram while every service quietly depends on the others.&lt;/p&gt;

&lt;p&gt;Then the broker. "We'll use Kafka" isn't a design decision. That middle box can be three different things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A queue hands each message to one worker, and once it's processed it's gone. Great for spreading work out.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A log keeps events in order and keeps them around, so each consumer reads at its own pace and can replay the past.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A router checks each event against rules and pushes it to whoever subscribed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pick the wrong one and you end up bolting replay onto a queue, or fighting a log to do basic job distribution.&lt;/p&gt;

&lt;p&gt;The consumer side has its own trap. A producer renames one field, and a consumer nobody remembered breaks in production.&lt;/p&gt;

&lt;p&gt;And the one people mix up most: event-driven and async are different things.&lt;/p&gt;

&lt;p&gt;You can throw work onto a background job queue and still have a tightly coupled system. Async is about when the work runs. Event-driven is about who needs to know about whom.&lt;/p&gt;

&lt;p&gt;So EDA won't fix your scaling problem on its own. It hands you trade-offs, and you want to pick them on purpose.&lt;/p&gt;

&lt;p&gt;I just published a free course that opens all three boxes, whether you are new to EDA or you have worked with it before. This video is going to change how you think and use EDA in your projects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/W25_BbZCZD0?si=VJXt5d1RZ6qjGptH" rel="noopener noreferrer"&gt;https://youtu.be/W25_BbZCZD0?si=VJXt5d1RZ6qjGptH&lt;/a&gt;&lt;/p&gt;

</description>
      <category>eventdriven</category>
      <category>systemdesign</category>
      <category>microservices</category>
      <category>distributedsystems</category>
    </item>
    <item>
      <title>Load Balancer Explained</title>
      <dc:creator>Joud Awad</dc:creator>
      <pubDate>Mon, 05 Oct 2026 15:15:27 +0000</pubDate>
      <link>https://dev.to/thejoud1997/load-balancer-explained-1npm</link>
      <guid>https://dev.to/thejoud1997/load-balancer-explained-1npm</guid>
      <description>&lt;p&gt;A load balancer is more than a box you draw in your system design diagram. It's one of the most critical pieces in your whole system, and if it goes down, it takes everything behind it down with it.&lt;/p&gt;

&lt;p&gt;The general idea is simple. It's the entry point to your servers. It sits in front of them and spreads the traffic between them. For most people that's where the understanding stops, and honestly it's enough to draw it in an interview.&lt;/p&gt;

&lt;p&gt;But this one component carries a lot of complexity. Changing a single option can completely change how your servers behave. Switch the hashing method and adding one server can move most of your users to a different machine. Put retries in the wrong place and one struggling database can get hit with hundreds of times its normal load. Pick layer 4 when you needed layer 7 and you lose the ability to route by URL at all.&lt;/p&gt;

&lt;p&gt;That's why understanding the different algorithms, what each network layer gives you, and how the balancer itself stays up matters so much. It's the difference between drawing a load balancer and actually knowing what it does and how to scale it with your system.&lt;/p&gt;

&lt;p&gt;In this video I break down every concept of load balancing, starting with the simplest thing it does, distributing load, and building up to the bigger pieces like high availability, global load balancing across regions, and load balancing between services.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/WmzB4MJcCiU?si=5i4Oyh7cme-BEgke" rel="noopener noreferrer"&gt;https://youtu.be/WmzB4MJcCiU?si=5i4Oyh7cme-BEgke&lt;/a&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>distributedsystems</category>
      <category>softwareengineering</category>
      <category>backend</category>
    </item>
    <item>
      <title>Object Storage for System Design</title>
      <dc:creator>Joud Awad</dc:creator>
      <pubDate>Mon, 28 Sep 2026 15:45:39 +0000</pubDate>
      <link>https://dev.to/thejoud1997/object-storage-for-system-design-3bm8</link>
      <guid>https://dev.to/thejoud1997/object-storage-for-system-design-3bm8</guid>
      <description>&lt;p&gt;Every growing app eventually runs into a file storage problem.&lt;/p&gt;

&lt;p&gt;Videos, images, backups, datasets. At some point every growing app hits the same wall: files get too big and too many for a database or a single server's disk.&lt;/p&gt;

&lt;p&gt;That's where object storage comes in.&lt;/p&gt;

&lt;p&gt;S3, Google Cloud Storage, Azure Blob Storage: they all solve the same problem. One central place that can hold any type of file, at almost any scale.&lt;/p&gt;

&lt;p&gt;But most engineers only use them at the surface level: upload, download, done.&lt;/p&gt;

&lt;p&gt;In my latest video, I go deeper:&lt;/p&gt;

&lt;p&gt;→ How object storage works internally&lt;br&gt;
→ Why it scales in ways a file system can't&lt;br&gt;
→ The design patterns for using it correctly in real systems&lt;/p&gt;

&lt;p&gt;If you're working in backend development or preparing for system design interviews, this is one of those fundamentals worth understanding properly.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/anLX4upY0ks" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>objectstorage</category>
      <category>software</category>
      <category>architecture</category>
    </item>
    <item>
      <title>CDN For System Design</title>
      <dc:creator>Joud Awad</dc:creator>
      <pubDate>Mon, 14 Sep 2026 16:15:23 +0000</pubDate>
      <link>https://dev.to/thejoud1997/cdn-for-system-design-n7a</link>
      <guid>https://dev.to/thejoud1997/cdn-for-system-design-n7a</guid>
      <description>&lt;p&gt;Say "add a CDN" in a system design interview and the next four questions decide whether you pass.&lt;/p&gt;

&lt;p&gt;One photo answers all four. Uploaded once to a server in Virginia. Opened by someone in Sydney.&lt;/p&gt;

&lt;p&gt;Before a single line of your code runs, geography has already charged that viewer about 930 milliseconds. A bigger server fixes none of it.&lt;/p&gt;

&lt;p&gt;The four questions, usually within thirty seconds:&lt;/p&gt;

&lt;p&gt;What is your cache key? What does a TTL expiry cost the origin? Which edge answers, and why? How do you serve a private file from a public machine?&lt;/p&gt;

&lt;p&gt;I followed that one photo for 44 minutes through all four. A few things I wish someone had told me earlier.&lt;/p&gt;

&lt;p&gt;Most engineers think the cache key is the URL. It isn't. It's the method plus the URI plus whatever your config or a Vary header bolts on. CloudFront's default CachingOptimized policy ignores query strings entirely. Cloudflare's default includes the full query string, verbatim, order included. Same photo URL, opposite behavior, two vendors.&lt;/p&gt;

&lt;p&gt;Add Vary: User-Agent and you get one cache entry per browser build. One extra header can take a hit ratio from the high nineties into single digits.&lt;/p&gt;

&lt;p&gt;A long TTL is permission, not a guarantee.&lt;/p&gt;

&lt;p&gt;Eviction happens whenever the edge wants the space back. And when a viral object does expire, it expires on every tier at once, so edges everywhere turn around and hit your origin in the same window. That's the thundering herd. Request collapsing and Origin Shield exist so that as few as one request per object reaches you.&lt;/p&gt;

&lt;p&gt;Purges are priced by the path you submit, not the files it clears. CloudFront gives you 1,000 free paths a month, then $0.005 each. Which is the actual argument for versioned filenames: photo.a3f9.jpg never needs purging.&lt;/p&gt;

&lt;p&gt;Which edge answers? GeoDNS guesses from your resolver's address, not yours. EDNS Client Subnet patches the guess. Anycast removes it: every edge announces the same IP, and failover becomes a routing event with no DNS TTL to wait out.&lt;/p&gt;

&lt;p&gt;And the number interviewers ask for is the wrong one. Going from 90% to 95% hit ratio sounds like five points. It halves your origin load. Origin offload is the metric. Hit ratio is the proxy.&lt;/p&gt;

&lt;p&gt;The private file? Signed URLs for a single object. Signed cookies when one viewer needs a hundred of them.&lt;/p&gt;

&lt;p&gt;Full walkthrough, one photo end to end, built from the vendor docs and the RFCs rather than folklore:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=gV_z0uG8_uo" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=gV_z0uG8_uo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>backend</category>
      <category>systemdesign</category>
      <category>architecture</category>
      <category>distributedsystems</category>
    </item>
    <item>
      <title>Circuit Breaker Pattern Explained</title>
      <dc:creator>Joud Awad</dc:creator>
      <pubDate>Mon, 07 Sep 2026 15:25:36 +0000</pubDate>
      <link>https://dev.to/thejoud1997/circuit-breaker-pattern-explained-ln2</link>
      <guid>https://dev.to/thejoud1997/circuit-breaker-pattern-explained-ln2</guid>
      <description>&lt;p&gt;Payments went fully down, and checkout was fine.&lt;/p&gt;

&lt;p&gt;The next week payments stayed up and answered in 30 seconds instead of 40 milliseconds. The entire site went dark.&lt;/p&gt;

&lt;p&gt;A dead dependency is a small problem. A slow one takes everything with it.&lt;/p&gt;

&lt;p&gt;Every call still waiting is holding a thread, a database connection and a chunk of memory that the product page needed too. Nothing throws an error. The pool is just gone.&lt;/p&gt;

&lt;p&gt;That's the cascading failure a circuit breaker exists to stop — and it's why the breaker is never installed on its own. A request meets a timeout, then a retry policy, then the breaker, then a fallback. In that order.&lt;/p&gt;

&lt;p&gt;Most of us built that chain from a tutorial that said "open after 5 consecutive failures."&lt;/p&gt;

&lt;p&gt;Go read your actual config.&lt;/p&gt;

&lt;p&gt;Resilience4j, Hystrix, Polly and gobreaker don't count consecutive failures. They trip on a failure rate across a sliding window, gated by a minimum call volume. Which is better — until you notice that on a low-traffic endpoint, two of those defaults combine to leave the breaker unable to open at all. Not "slow to open." Unable.&lt;/p&gt;

&lt;p&gt;Three more things I had wrong for years:&lt;/p&gt;

&lt;p&gt;Retries are selfish. Exponential backoff without jitter doesn't spread the load, it just reschedules the same spike for later.&lt;/p&gt;

&lt;p&gt;You can have full throughput and zero goodput at the same time, and every dashboard will look busy while nothing succeeds.&lt;/p&gt;

&lt;p&gt;And AWS's own Builders' Library warns that circuit breakers add modal behavior and recovery time — its SDK ships a retry token bucket instead. Amazon has a written case against fallback code, too. The pattern everyone teaches as the answer is the one Amazon argues you should think twice about.&lt;/p&gt;

&lt;p&gt;So I built the version that includes the numbers and the counterarguments: 36 minutes, one call from checkout to payments, all the way through.&lt;/p&gt;

&lt;p&gt;If you take one thing: an open breaker with no alarm on its state changes is a silent partial outage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/rvKKj7JU92g" rel="noopener noreferrer"&gt;https://youtu.be/rvKKj7JU92g&lt;/a&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>microservices</category>
      <category>backend</category>
      <category>software</category>
    </item>
    <item>
      <title>Database Internals For System Design</title>
      <dc:creator>Joud Awad</dc:creator>
      <pubDate>Mon, 31 Aug 2026 15:56:17 +0000</pubDate>
      <link>https://dev.to/thejoud1997/database-internals-for-system-design-1fl4</link>
      <guid>https://dev.to/thejoud1997/database-internals-for-system-design-1fl4</guid>
      <description>&lt;p&gt;They added an index and the query got slower.&lt;/p&gt;

&lt;p&gt;Then they doubled the instance size and bought back 400 milliseconds.&lt;/p&gt;

&lt;p&gt;So they put Redis in front of it. The hit rate came back at 4 percent. Then they added a read replica, and it fell 45 seconds behind.&lt;/p&gt;

&lt;p&gt;Four fixes. All reasonable. All wrong.&lt;/p&gt;

&lt;p&gt;None of it was bad luck. Every one of those numbers was predictable from what the engine was doing underneath the query.&lt;/p&gt;

&lt;p&gt;The index lost because the planner's row estimate was off — and an index scan is two hops, find the entry, then go fetch the row. Past enough rows, reading the pages straight through just wins.&lt;/p&gt;

&lt;p&gt;The 4 percent wasn't a Redis problem. It was the diagnosis. A cache is a second buffer pool. If the working set doesn't fit in the first one, it isn't going to fit in the second one either.&lt;/p&gt;

&lt;p&gt;And the replica lag came from the same place. Replication is the write-ahead log, shipped. An UPDATE in Postgres never overwrites a row — it writes a new version. More versions, more WAL, more lag.&lt;/p&gt;

&lt;p&gt;Same layer, three times. Storage.&lt;/p&gt;

&lt;p&gt;Most of us learned databases top-down: write the query, add an index when it's slow, add a replica when the index stops helping. That's backwards. Indexes make no sense without pages. Joins make no sense without indexes. And nobody explains the WAL until the replica is already 45 seconds behind.&lt;/p&gt;

&lt;p&gt;So I built the bottom-up version I wish I'd had.&lt;/p&gt;

&lt;p&gt;2 hours 22 minutes. Seven layers — storage, indexes, pagination, execution, transactions, read scaling, schema. One query, one 200 million row table, all the way up. Seven checkpoint quizzes with real countdowns, so you answer before you hear the answer.&lt;/p&gt;

&lt;p&gt;If you only watch part of it, watch the bottom four.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/uy2yom0AlhA" rel="noopener noreferrer"&gt;https://youtu.be/uy2yom0AlhA&lt;/a&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>systemdesign</category>
      <category>distributedsystems</category>
      <category>backend</category>
    </item>
    <item>
      <title>DynamoDB Client API Tutorial: Query, Pagination, Cost Explained</title>
      <dc:creator>Joud Awad</dc:creator>
      <pubDate>Mon, 24 Aug 2026 09:24:02 +0000</pubDate>
      <link>https://dev.to/thejoud1997/dynamodb-client-api-tutorial-query-pagination-cost-explained-24hi</link>
      <guid>https://dev.to/thejoud1997/dynamodb-client-api-tutorial-query-pagination-cost-explained-24hi</guid>
      <description>&lt;p&gt;There is no SQL in DynamoDB.&lt;/p&gt;

&lt;p&gt;No query language, no syntax to memorize, no planner deciding how your request gets run. You import a client and you call a method.&lt;/p&gt;

&lt;p&gt;In Postgres, "give me one row" and "give me a thousand rows" are the same SELECT with different clauses, and the engine works out the rest. In DynamoDB those are different methods and you're the one choosing. GetItem for a single item by its key. BatchGetItem for up to 100 of them. Query for a run of items under one partition key. Scan for when you've given up and want the whole table.&lt;/p&gt;

&lt;p&gt;The method name is the operation. That's the shift people miss coming from SQL: you're not composing a statement, you're picking an action. One item or many, atomic or not, read or write. Three decisions, and the entire client API falls out of them.&lt;/p&gt;

&lt;p&gt;What you do have to learn is the cost, because it isn't hidden behind a planner any more. 4 KB read blocks, 1 KB write blocks, and a round-up rule that makes a 200-byte item cost a full block. A strongly consistent read costs double an eventual one. A read inside a transaction doubles again. Once you know which method you called, you can price the call before you run it.&lt;/p&gt;

&lt;p&gt;So I ran every one of them on camera, from real NestJS code, with the consumed capacity on screen next to each call.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/JeyZ-kN0H7Y?si=ZkvqVIC1TCjCX06k" rel="noopener noreferrer"&gt;https://youtu.be/JeyZ-kN0H7Y?si=ZkvqVIC1TCjCX06k&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>dynamodb</category>
      <category>nosql</category>
      <category>backend</category>
    </item>
    <item>
      <title>DynamoDB Table Design: Complete Data Modeling Guide</title>
      <dc:creator>Joud Awad</dc:creator>
      <pubDate>Thu, 20 Aug 2026 16:16:51 +0000</pubDate>
      <link>https://dev.to/thejoud1997/dynamodb-table-design-complete-data-modeling-guide-3of9</link>
      <guid>https://dev.to/thejoud1997/dynamodb-table-design-complete-data-modeling-guide-3of9</guid>
      <description>&lt;p&gt;DynamoDB Data modeling is one of the hardest things that appears on paper. Still, once you understand the different access patterns and how DynamoDB queries your data, it starts being an easy task.&lt;/p&gt;

&lt;p&gt;DynamoDB uses a unique combination of Partition Key (PK) and sort keys (SK) in order to store and query your data, and understanding how those two works under the hood is the first part of working with DynamoDB, the hard part and the most challenging is to understand how to model your data, how to model your access pattern, and how you can extract questions from your own system and convert them into a working DynamoDB Tables.&lt;/p&gt;

&lt;p&gt;In this video, we walk you through a full DynamoDB end-to-end table design, covering all the access patterns DynamoDB uses to build &lt;em&gt;&lt;strong&gt;three&lt;/strong&gt;&lt;/em&gt; real-world case examples.&lt;/p&gt;

&lt;p&gt;At the end of this video, you will be able to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Understand how DynamoDB Data Modeling works.&lt;/li&gt;
&lt;li&gt;Build your own DynamoDB Tables.&lt;/li&gt;
&lt;li&gt;Convert your own use case into a question DynamoDB is able to answer for you.&lt;/li&gt;
&lt;li&gt;Model any real-world use case that you may face in your own application.&lt;/li&gt;
&lt;li&gt;Master the Single-Table Design in DynamoDB&lt;/li&gt;
&lt;li&gt;Work and interact with all the differnet access patterns DynamoDB provide to you.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Video Link: &lt;a href="https://www.youtube.com/watch?v=rbP1jGNzG2A" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=rbP1jGNzG2A&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>database</category>
      <category>dynamodb</category>
      <category>backend</category>
    </item>
    <item>
      <title>Caching For System Design: Redis, CDN, Cache Patterns Explained</title>
      <dc:creator>Joud Awad</dc:creator>
      <pubDate>Mon, 17 Aug 2026 15:53:52 +0000</pubDate>
      <link>https://dev.to/thejoud1997/caching-for-system-design-redis-cdn-cache-patterns-explained-5407</link>
      <guid>https://dev.to/thejoud1997/caching-for-system-design-redis-cdn-cache-patterns-explained-5407</guid>
      <description>&lt;p&gt;A 99% cache hit rate means your database has never been load tested&lt;br&gt;
at real traffic.&lt;/p&gt;

&lt;p&gt;It has only ever seen 1% of it.&lt;/p&gt;

&lt;p&gt;Wikimedia published the postmortem. Their hit ratio fell while demand&lt;br&gt;
stayed flat, and the origin took five times its normal load. Nothing&lt;br&gt;
else changed. The cache just stopped absorbing.&lt;/p&gt;

&lt;p&gt;Which means the number on your dashboard is not a performance metric.&lt;br&gt;
It is the size of your outage.&lt;/p&gt;

&lt;p&gt;I went through primary sources on caching for a video recently, and&lt;br&gt;
that reframe was the one that stuck. A cache is a second copy of your&lt;br&gt;
data. Every hard question after that is about the copy, not the cache.&lt;/p&gt;

&lt;p&gt;Then there is the cost, which most advice treats as settled. Memory&lt;br&gt;
is cheap, databases are expensive, therefore cache. I priced it out&lt;br&gt;
in August 2026. A cache node runs about 21% cheaper than a comparable&lt;br&gt;
read replica per gigabyte. Not an order of magnitude. Twenty-one&lt;br&gt;
percent.&lt;/p&gt;

&lt;p&gt;A cache pays for the traffic it absorbs and nothing else. That is the&lt;br&gt;
entire business case.&lt;/p&gt;

&lt;p&gt;The patterns everyone teaches do not survive checking either.&lt;br&gt;
Write-through has three incompatible vendor definitions. AWS lists&lt;br&gt;
"never stale" as an advantage. Microsoft ships a repair function&lt;br&gt;
because the cache write can fail after the commit. Write-around, the&lt;br&gt;
fourth column in every caching-patterns table online, appears in none&lt;br&gt;
of the nine primary sources I checked.&lt;/p&gt;

&lt;p&gt;And there is one test almost nobody runs. It is a single sentence in&lt;br&gt;
AWS's own guidance: run load tests with caches disabled.&lt;/p&gt;

&lt;p&gt;Full breakdown, 65 minutes, chaptered, every claim tied to a primary&lt;br&gt;
source: &lt;a href="https://youtu.be/ETvLl-8bPbo" rel="noopener noreferrer"&gt;https://youtu.be/ETvLl-8bPbo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What is inside the box, the six layers a request passes through, the&lt;br&gt;
write patterns, the failure modes, and the cost math.&lt;/p&gt;

</description>
      <category>redis</category>
      <category>backend</category>
      <category>systemdesign</category>
      <category>distributedsystems</category>
    </item>
    <item>
      <title>System Design Crash Course: Scaling 100 to 100M Users</title>
      <dc:creator>Joud Awad</dc:creator>
      <pubDate>Mon, 10 Aug 2026 16:11:43 +0000</pubDate>
      <link>https://dev.to/thejoud1997/system-design-crash-course-scaling-100-to-100m-users-3hi2</link>
      <guid>https://dev.to/thejoud1997/system-design-crash-course-scaling-100-to-100m-users-3hi2</guid>
      <description>&lt;p&gt;Most systems don't break at 100 million users.&lt;/p&gt;

&lt;p&gt;They break at 5,000, because someone architected for 100 million.&lt;/p&gt;

&lt;p&gt;Every scaling stage has exactly one bottleneck. Solve that one. Ignore the rest.&lt;/p&gt;

&lt;p&gt;100 users: one server. App, database, static files, all of it. This takes you further than you think, and it's the only stage where you can debug production by reading a single log file.&lt;/p&gt;

&lt;p&gt;10,000 users: your database is competing with your app for CPU. Split them onto separate boxes. Nothing else. Not microservices, not Kafka.&lt;/p&gt;

&lt;p&gt;100,000 users: one app instance can't hold the traffic. Add a load balancer and a second instance. The moment you do, session state in memory becomes a bug. Move sessions out.&lt;/p&gt;

&lt;p&gt;1 million users: reads are drowning your primary database. Read replicas and a cache layer. Most teams ship the cache and skip the invalidation strategy, then spend a quarter chasing stale data.&lt;/p&gt;

&lt;p&gt;10 million users: your bottleneck is geographic, not computational. A request from Singapore to us-east-1 spends roughly 200ms in network round trips before your code runs. CDN for static assets, then regional deployments.&lt;/p&gt;

&lt;p&gt;100 million users: now you shard. Not before. Sharding trades away joins, cross-entity transactions, and easy schema migrations in exchange for write throughput. It is a permanent decision.&lt;/p&gt;

&lt;p&gt;What most scaling content gets wrong:&lt;/p&gt;

&lt;p&gt;It presents these as a checklist of technologies to adopt. They aren't. Each stage is a specific failure mode with a specific fix, and applying a stage-six fix at stage two buys you the operational cost of a large system with the traffic of a small one.&lt;/p&gt;

&lt;p&gt;I've watched a team run Kubernetes and a service mesh to serve 400 requests per minute. The tooling wasn't wrong. The timing was.&lt;/p&gt;

&lt;p&gt;Scale isn't a number you design for. It's a sequence of bottlenecks you meet one at a time.&lt;/p&gt;

&lt;p&gt;I put the full progression into a visual walkthrough: the architecture at every stage, and the exact signal that tells you it's time to move to the next one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/fwVGulYwlak" rel="noopener noreferrer"&gt;https://youtu.be/fwVGulYwlak&lt;/a&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>software</category>
      <category>backend</category>
      <category>distributedsystems</category>
    </item>
    <item>
      <title>Observability Crash Course</title>
      <dc:creator>Joud Awad</dc:creator>
      <pubDate>Mon, 03 Aug 2026 15:36:31 +0000</pubDate>
      <link>https://dev.to/thejoud1997/observability-crash-course-38ni</link>
      <guid>https://dev.to/thejoud1997/observability-crash-course-38ni</guid>
      <description>&lt;p&gt;Observability is being able to look inside a running system.&lt;/p&gt;

&lt;p&gt;Not at one moment you planned for. At any moment, and understand what it's actually doing.&lt;/p&gt;

&lt;p&gt;It takes several components working together to make a system visible from the outside.&lt;/p&gt;

&lt;p&gt;This week's deep dive on System Design Labs is a full crash course.&lt;/p&gt;

&lt;p&gt;The pillars, how they fit, and how to follow one request end to end across the whole system.&lt;/p&gt;

&lt;p&gt;We cover OpenTelemetry, logs, metrics, traces, SLOs, sampling, profiling, eBPF, and more.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/umm-MyCl3Q4" rel="noopener noreferrer"&gt;https://youtu.be/umm-MyCl3Q4&lt;/a&gt;&lt;/p&gt;

</description>
      <category>backend</category>
      <category>devops</category>
      <category>sre</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Day 12/30 AWS System Design Patterns</title>
      <dc:creator>Joud Awad</dc:creator>
      <pubDate>Sat, 01 Aug 2026 16:45:23 +0000</pubDate>
      <link>https://dev.to/thejoud1997/day-1230-aws-system-design-patterns-479d</link>
      <guid>https://dev.to/thejoud1997/day-1230-aws-system-design-patterns-479d</guid>
      <description>&lt;p&gt;A document processing pipeline runs as an AWS Step Functions Standard workflow (serverless workflow orchestrator — Standard tier bills per state transition, not per execution or per second). Seven top-level states: receive document, validate format, extract text, run classification, store result, notify downstream, update audit log. The extract-text state is a Map state (fans out over an array — each item runs its own sub-workflow, and every state inside every iteration is billed as a transition) that processes the document page by page. Documents average 9 pages, and each page runs a 7-state pipeline: render, OCR, confidence check, a retry choice, redaction, store page, emit metrics.&lt;/p&gt;

&lt;p&gt;Average execution takes 4–6 seconds end to end.&lt;/p&gt;

&lt;p&gt;When the pipeline processed 80,000 documents per month, the Step Functions bill was $140. The platform grew. Last month it processed 2.2 million documents. The bill was $3,850.&lt;/p&gt;

&lt;p&gt;Nothing changed in the workflow. No new states were added. The team is deciding whether to optimize or migrate.&lt;/p&gt;

&lt;p&gt;What is the correct explanation, and what is the right fix?&lt;/p&gt;

&lt;p&gt;A) Step Functions Standard pricing is per execution at a flat rate — 2.2M executions scaled the cost linearly and only reducing volume can reduce it; but Standard Workflows are not priced per execution — the billable unit is the state transition, and a single execution can contain a few transitions or hundreds&lt;/p&gt;

&lt;p&gt;B) Standard bills every state transition, and the Map state multiplies them — 7 top-level states plus 9 pages × 7 states per page is roughly 70 transitions per document; at 2.2M documents that is ~154M transitions, and at $0.025 per 1,000 transitions, $3,850; the bill scales with documents × pages, not documents&lt;/p&gt;

&lt;p&gt;C) Step Functions Standard includes a per-second execution charge — longer executions at higher volume caused the spike; but duration billing is the Express Workflow model; a Standard execution that sits in a Wait state for 24 hours costs the same transitions as one finishing in 4 seconds&lt;/p&gt;

&lt;p&gt;D) The increase is CloudWatch Logs (AWS monitoring, charges per GB ingested) ingestion from execution history — a real cost at scale, but a 27× bill jump from $140 to $3,850 with unchanged logging configuration cannot come from log ingestion&lt;/p&gt;

&lt;p&gt;Answer in the comments.&lt;/p&gt;

</description>
      <category>eventdriven</category>
      <category>aws</category>
      <category>serverless</category>
      <category>distributedsystems</category>
    </item>
  </channel>
</rss>
