<?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: Hongster</title>
    <description>The latest articles on DEV Community by Hongster (@hongster85).</description>
    <link>https://dev.to/hongster85</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%2F1600971%2Fe50d3487-f18f-404f-85ed-c5618bbd2777.jpeg</url>
      <title>DEV Community: Hongster</title>
      <link>https://dev.to/hongster85</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hongster85"/>
    <language>en</language>
    <item>
      <title>Event Sourcing : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Thu, 02 Jul 2026 14:00:28 +0000</pubDate>
      <link>https://dev.to/hongster85/event-sourcing-understand-in-3-minutes-4hk</link>
      <guid>https://dev.to/hongster85/event-sourcing-understand-in-3-minutes-4hk</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Event Sourcing&lt;/strong&gt; is a data storage pattern where you save every state-changing event that happens in your system, instead of saving just the current state. You might encounter this need when your traditional CRUD database starts feeling like a bottleneck—maybe you’re losing audit trails, struggling to debug complex workflows, or needing to replay past states for machine learning or compliance. Sound familiar? It’s the kind of problem that creeps up once your app grows past a simple to-do list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Explanation
&lt;/h2&gt;

&lt;p&gt;Event Sourcing flips your mental model upside down. Instead of updating a row in a database (like changing a user’s email from “&lt;a href="mailto:old@example.com"&gt;old@example.com&lt;/a&gt;” to “&lt;a href="mailto:new@example.com"&gt;new@example.com&lt;/a&gt;”), you &lt;em&gt;append&lt;/em&gt; an event to an immutable log: “User changed their email from X to Y.” The current state of that user is then derived by replaying all events that have ever happened for them.&lt;/p&gt;

&lt;p&gt;Here’s how it works in practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Events are facts.&lt;/strong&gt; Each event represents something that happened in the past—never deleted, never updated. Example: &lt;code&gt;OrderPlaced&lt;/code&gt;, &lt;code&gt;PaymentReceived&lt;/code&gt;, &lt;code&gt;ItemShipped&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event store is the source of truth.&lt;/strong&gt; This is just a database optimized for appending events (often with a sequence ID or timestamp). You don’t have a separate “current state” table.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Projections build read-models.&lt;/strong&gt; To answer “What is the user’s current email?” you run a function that folds all &lt;code&gt;EmailChanged&lt;/code&gt; events for that user into a single value. This can be done on the fly or precomputed as a “projection” stored in a cache or separate read database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Snapshots avoid endless replays.&lt;/strong&gt; As events accumulate, you periodically take a snapshot of the state at a point in time. Later replays start from the snapshot instead of event #1.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Analogy:&lt;/strong&gt; Think of a bank account ledger. Traditional CRUD is like keeping a sticky note with your current balance—you erase and rewrite it each time. Event Sourcing is keeping the full log of every deposit and withdrawal. To know your balance, you sum the log. Want to know what your balance was last Tuesday? Just replay the log up to that date. You never lose history.&lt;/p&gt;

&lt;p&gt;Key components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Event&lt;/strong&gt; – immutable, named, timestamped data (e.g., &lt;code&gt;{"type": "ItemAddedToCart", "timestamp": ..., "data": {"itemId":..., "quantity":1}}&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event Store&lt;/strong&gt; – append-only storage (like Kafka, EventStoreDB, or a dedicated table in PostgreSQL)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aggregate&lt;/strong&gt; – a cluster of events that belong together (e.g., all events for one shopping cart)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Projection&lt;/strong&gt; – a function that transforms the event stream into a useful read model&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Practical Context
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;When to use Event Sourcing:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need a full audit trail (financial systems, compliance-heavy apps)&lt;/li&gt;
&lt;li&gt;You want to debug or replay past system states (temporal queries, testing, or customer support)&lt;/li&gt;
&lt;li&gt;Your business logic is complex and involves long-running workflows that need to recover gracefully from failures&lt;/li&gt;
&lt;li&gt;You’re building microservices and need to share facts between services (event-driven architecture)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Your data is simple CRUD with low volume (a blog’s comment count or a user profile—overkill)&lt;/li&gt;
&lt;li&gt;You need strong eventual consistency guarantees and can’t accept temporary stale reads&lt;/li&gt;
&lt;li&gt;Your team is new to event-driven patterns and the operational complexity (event versioning, schema evolution, projection rebuilding) will slow you down&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Common real-world use cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;E-commerce order management:&lt;/strong&gt; Tracking every state change of an order (placed, paid, shipped, refunded) so you can later analyze funnel conversion, handle refunds, or reprocess failed payments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Banking &amp;amp; accounting:&lt;/strong&gt; Immutable transaction logs for compliance, fraud detection, and year-end reporting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collaborative tools (like GitHub):&lt;/strong&gt; Recording every edit, comment, and merge as events so you can rebuild any historical version of a document or codebase.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick Example
&lt;/h2&gt;

&lt;p&gt;Imagine a shopping cart. With &lt;strong&gt;traditional CRUD&lt;/strong&gt;, you’d have a &lt;code&gt;cart&lt;/code&gt; table with columns like &lt;code&gt;user_id&lt;/code&gt;, &lt;code&gt;items&lt;/code&gt; (a JSON blob), and &lt;code&gt;total&lt;/code&gt;. On “add item,” you update the row. If something crashes mid-update, you might lose data.&lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;Event Sourcing&lt;/strong&gt;, you store events:&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="c1"&gt;// Appending an event to the event store&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eventType&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ItemAddedToCart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aggregateId&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cart-123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;itemId&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;item-456&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;quantity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;price&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;9.99&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;timestamp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2024-03-15T10:00:00Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To get the current cart state, you replay all events for &lt;code&gt;cart-123&lt;/code&gt; and fold them:&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="c1"&gt;// Replay events to compute current cart&lt;/span&gt;
&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ItemAddedToCart&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;cart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// other event types...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tiny example shows the core trade-off: you get perfect history and traceability, but you have to explicitly rebuild state (or maintain projections). It’s not more code—it’s different code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Event Sourcing trades simplicity of state management for the superpower of immutable, replayable history.&lt;/strong&gt; Use it when you care deeply about what &lt;em&gt;happened&lt;/em&gt;, not just what &lt;em&gt;is&lt;/em&gt;. For a deeper dive, start with Martin Fowler’s classic bliki post on Event Sourcing—it’s the gold standard for understanding the pattern’s nuances.&lt;/p&gt;

</description>
      <category>eventsourcing</category>
      <category>eventstore</category>
      <category>immutablelog</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Repository Pattern : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Tue, 30 Jun 2026 14:00:30 +0000</pubDate>
      <link>https://dev.to/hongster85/repository-pattern-understand-in-3-minutes-18g5</link>
      <guid>https://dev.to/hongster85/repository-pattern-understand-in-3-minutes-18g5</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Repository Pattern&lt;/strong&gt; is a design pattern that acts as a middleman between your application's business logic and your data storage, giving you a clean, consistent interface to access and manipulate data without caring whether it lives in a database, a file, or an API. You've probably run into that codebase where data access logic is scattered everywhere—SQL queries in controllers, raw database calls in services, and tests that break because they can't mock the database. It's messy, hard to change, and even harder to test. If you've ever spent a week untangling spaghetti just to swap out a database, you already know why this pattern exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Explanation
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Repository Pattern&lt;/strong&gt; works by creating a clean abstraction layer that hides the messy details of data storage. Think of it like a &lt;strong&gt;restaurant menu&lt;/strong&gt;—you order a "burger" (the what), and the kitchen handles the "how" (grilling, sourcing ingredients, plating). You don't need to know if the beef came from a local farm or a freezer. Similarly, a repository says "here are methods to get and save data" (like &lt;code&gt;findUser(id)&lt;/code&gt; or &lt;code&gt;saveOrder(order)&lt;/code&gt;), while hiding whether that data lives in PostgreSQL, MongoDB, or a simple in-memory list.&lt;/p&gt;

&lt;p&gt;Key components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Repository interface&lt;/strong&gt; — A contract that defines all data operations (e.g., &lt;code&gt;getAll()&lt;/code&gt;, &lt;code&gt;getById()&lt;/code&gt;, &lt;code&gt;save()&lt;/code&gt;, &lt;code&gt;delete()&lt;/code&gt;). Your business logic depends on this interface, not on any concrete implementation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concrete repository&lt;/strong&gt; — The actual implementation that talks to your specific data source. Could use raw SQL, an ORM, or a third-party API. This is the only part that changes when you switch storage backends.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client code&lt;/strong&gt; — Your services, controllers, or use cases that call the repository methods. They never import a database driver—only the repository interface.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The core idea: &lt;strong&gt;your application logic doesn't know or care where data comes from&lt;/strong&gt;. It just asks the repository for what it needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Context
&lt;/h2&gt;

&lt;p&gt;Use the &lt;strong&gt;Repository Pattern&lt;/strong&gt; when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need to &lt;strong&gt;unit test business logic&lt;/strong&gt; without a real database (mock the repository instead).&lt;/li&gt;
&lt;li&gt;You're building an app that might &lt;strong&gt;switch databases&lt;/strong&gt; (e.g., from SQLite in dev to PostgreSQL in production, or from MySQL to a REST API).&lt;/li&gt;
&lt;li&gt;You want to &lt;strong&gt;centralize data access logic&lt;/strong&gt; (caching, logging, retries) in one place instead of sprinkling it across controllers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Don't use it&lt;/strong&gt; when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your app is a simple CRUD wrapper with no complex business logic—a basic ORM is already your repository.&lt;/li&gt;
&lt;li&gt;You're building a prototype or small app that won't live long enough to justify the abstraction overhead.&lt;/li&gt;
&lt;li&gt;Your data source is already simple and stable (like reading from a local JSON file with no transformations).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why you should care&lt;/strong&gt;: Without a repository, every change to your storage layer (new database, new ORM, different API) forces you to hunt down and rewrite dozens of files. With a repository, you change exactly &lt;strong&gt;one&lt;/strong&gt; file. That's it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Example
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Before (no repository)&lt;/strong&gt; — your controller directly uses an ORM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ordersController.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./database&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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;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="s1"&gt;SELECT * FROM orders WHERE 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;id&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After (with repository)&lt;/strong&gt; — the controller talks to an interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ordersRepository.ts&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;OrderRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;getById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;&amp;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;// ordersController.ts (no database imports!)&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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;ordersRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this demonstrates: The controller now works with &lt;strong&gt;any&lt;/strong&gt; data source that implements the &lt;code&gt;OrderRepository&lt;/code&gt; interface. You can swap from PostgreSQL to MongoDB, or create a mock for testing, without touching a single line of business logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Inject a repository interface where data meets logic&lt;/strong&gt;, and you'll free your application from being locked to any specific storage technology. Martin Fowler's "Patterns of Enterprise Application Architecture" book covers this pattern in depth if you want to go deeper.&lt;/p&gt;

</description>
      <category>repositorypattern</category>
      <category>dataaccess</category>
      <category>abstractionlayer</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>MVC vs MVP vs MVVM : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Thu, 25 Jun 2026 14:00:29 +0000</pubDate>
      <link>https://dev.to/hongster85/mvc-vs-mvp-vs-mvvm-understand-in-3-minutes-i9e</link>
      <guid>https://dev.to/hongster85/mvc-vs-mvp-vs-mvvm-understand-in-3-minutes-i9e</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;MVC, MVP, and MVVM&lt;/strong&gt; are three architectural patterns that solve the same fundamental problem: how to separate your user interface (UI) from your business logic and data. You encounter this dilemma every time you build a screen that displays data, handles user input, and updates the view—whether you're writing a web app, a mobile app, or a desktop tool. Without a clear structure, your code quickly turns into a tangled mess of event handlers and DOM queries that’s impossible to test, debug, or reuse. These patterns give you a proven blueprint to keep things organized, but choosing the wrong one can lead to unnecessary complexity or painful refactoring down the road.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Explanation
&lt;/h2&gt;

&lt;p&gt;All three patterns divide an application into three distinct roles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model&lt;/strong&gt; – The data and business logic (e.g., a user object, a database query, an API call).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;View&lt;/strong&gt; – The UI that the user sees and interacts with (e.g., a button, a list, a screen).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Controller / Presenter / ViewModel&lt;/strong&gt; – The glue that synchronizes the two.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key difference? &lt;strong&gt;How the View communicates back with the model.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  MVC (Model-View-Controller)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Controller&lt;/strong&gt; receives user input from the View, modifies the Model, and then tells the View to update.&lt;/li&gt;
&lt;li&gt;The View is &lt;strong&gt;passive&lt;/strong&gt; – it doesn’t know about the Model; it just renders what the Controller tells it.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Rough analogy:&lt;/em&gt; A restaurant kitchen. The Controller is the waiter who takes your order (input), tells the chef (Model) to cook, and then brings you the food (updates the View). You never talk to the chef directly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  MVP (Model-View-Presenter)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Presenter&lt;/strong&gt; is more active. It listens to the View’s events and directly manipulates the View (e.g., sets text, enables buttons).&lt;/li&gt;
&lt;li&gt;The View is a &lt;strong&gt;dumb&lt;/strong&gt; interface that exposes methods and events – the Presenter calls those methods.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Analogy:&lt;/em&gt; A puppeteer (Presenter) controlling a puppet (View). The puppet doesn’t think – it just does what the puppeteer makes it do.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  MVVM (Model-View-ViewModel)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;ViewModel&lt;/strong&gt; holds all the state and logic needed for the View, and exposes it through properties and commands.&lt;/li&gt;
&lt;li&gt;The View &lt;strong&gt;binds directly&lt;/strong&gt; to the ViewModel’s properties using data-binding (e.g., Angular, Vue, WPF). When the ViewModel changes, the View updates automatically; when the user interacts with the View, the ViewModel is notified.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Analogy:&lt;/em&gt; A spreadsheet. The ViewModel is the formula cells – change a value, and all linked cells update instantly. The View is just the grid that displays those cells.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Visual diagram (mental model):&lt;/strong&gt;&lt;/p&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;Input flow&lt;/th&gt;
&lt;th&gt;Update flow&lt;/th&gt;
&lt;th&gt;View’s role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;MVC&lt;/td&gt;
&lt;td&gt;View → Controller → Model → Controller → View&lt;/td&gt;
&lt;td&gt;Controller pushes update&lt;/td&gt;
&lt;td&gt;Passive, receives data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MVP&lt;/td&gt;
&lt;td&gt;View → Presenter → Model → Presenter → View&lt;/td&gt;
&lt;td&gt;Presenter pushes update&lt;/td&gt;
&lt;td&gt;Dumb, exposes interface&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MVVM&lt;/td&gt;
&lt;td&gt;View ↔ ViewModel (via bindings) ↔ Model&lt;/td&gt;
&lt;td&gt;ViewModel auto-updates View via bindings&lt;/td&gt;
&lt;td&gt;Declarative, reacts to changes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Practical Context
&lt;/h2&gt;

&lt;h3&gt;
  
  
  When to use which?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MVC&lt;/strong&gt; – Best for traditional server-rendered web apps (e.g., Ruby on Rails, ASP.NET MVC) or simple mobile apps where you want a lightweight separation. Use it when you need a clean, straightforward structure and don’t need complex two-way data binding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MVP&lt;/strong&gt; – Ideal for platforms with weak or no data-binding (e.g., Android Activities, WinForms). Use it when you need &lt;strong&gt;testability&lt;/strong&gt; – the Presenter can be unit-tested without the View’s UI framework. Also good when the View lifecycle is tricky (e.g., Android’s rotation).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MVVM&lt;/strong&gt; – The go-to for modern frameworks with built-in data-binding (e.g., Angular, Vue, React with hooks, SwiftUI, WPF). Use it when your UI is complex and state-heavy – the automatic synchronization saves you from writing tons of glue code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  When &lt;strong&gt;not&lt;/strong&gt; to use them?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Don’t use any pattern&lt;/strong&gt; for trivial screens (e.g., a static “About” page) – you’ll over-engineer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid MVP&lt;/strong&gt; if your framework already has data-binding – you’ll fight the framework.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid MVC&lt;/strong&gt; in highly interactive, real-time UIs – the manual update cycles become tedious.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why should you care?
&lt;/h3&gt;

&lt;p&gt;Because the right pattern makes your code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Testable&lt;/strong&gt; (logic separated from UI)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintainable&lt;/strong&gt; (changing the view doesn’t break logic)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reusable&lt;/strong&gt; (same Model can power different Views)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick Example
&lt;/h2&gt;

&lt;p&gt;Here’s a minimal &lt;strong&gt;MVVM&lt;/strong&gt; example for a counter button (using a conceptual JavaScript-like syntax):&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="c1"&gt;// Model&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CounterModel&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="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;count&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="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;increment&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;count&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ViewModel&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CounterViewModel&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;model&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;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;model&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;count&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="c1"&gt;// observable property&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;onIncrement&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;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;increment&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;count&lt;/span&gt; &lt;span class="o"&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;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// triggers view update via binding&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// View (HTML)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&amp;gt;  &amp;lt;!-- data-bound --&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;counter.onIncrement()&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What it shows:&lt;/strong&gt; The View knows nothing about the Model. It binds to &lt;code&gt;counter.count&lt;/code&gt; and calls &lt;code&gt;counter.onIncrement()&lt;/code&gt;. The ViewModel holds the state, updates the Model, and pushes changes back to the View through data-binding. No manual DOM manipulation – clean and testable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Choose MVVM when your framework supports data-binding, MVP when you need maximum testability, and MVC for simple, server-side apps.&lt;/strong&gt; If you’re still unsure, start with MVVM on modern mobile/web stacks – it scales best for complex UIs. For deeper dive, check out Martin Fowler’s GUI Architectures article.&lt;/p&gt;

</description>
      <category>mvvm</category>
      <category>mvp</category>
      <category>mvc</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Hashing vs Encryption : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Tue, 23 Jun 2026 14:00:26 +0000</pubDate>
      <link>https://dev.to/hongster85/hashing-vs-encryption-understand-in-3-minutes-321k</link>
      <guid>https://dev.to/hongster85/hashing-vs-encryption-understand-in-3-minutes-321k</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Hashing vs Encryption&lt;/strong&gt; is a choice every developer faces when deciding how to protect data—but mixing them up can lead to security holes that are both common and dangerous.&lt;br&gt;&lt;br&gt;
You might need to store user passwords, transmit sensitive files, or verify message integrity. Pick the wrong tool, and you either lose the ability to recover data when you need it, or you leave secrets exposed in ways that attackers love to exploit.&lt;/p&gt;
&lt;h2&gt;
  
  
  Core Explanation
&lt;/h2&gt;

&lt;p&gt;Think of &lt;strong&gt;hashing&lt;/strong&gt; as a one-way blender and &lt;strong&gt;encryption&lt;/strong&gt; as a lockable box with a key.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hashing&lt;/strong&gt; takes any input (a password, a file, a message) and produces a fixed-length string called a hash. The process is deterministic (same input always gives the same hash) but irreversible—you cannot “un-hash” the output to get the original data.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encryption&lt;/strong&gt; transforms data (plaintext) into ciphertext using an algorithm and a secret key. With the correct key, you can decrypt the ciphertext back to the original plaintext. Encryption is reversible by design.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Key differences at a glance
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Hashing&lt;/th&gt;
&lt;th&gt;Encryption&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Direction&lt;/td&gt;
&lt;td&gt;One-way only&lt;/td&gt;
&lt;td&gt;Two-way (encrypt/decrypt)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reversible?&lt;/td&gt;
&lt;td&gt;No (computationally infeasible)&lt;/td&gt;
&lt;td&gt;Yes (with the right key)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output length&lt;/td&gt;
&lt;td&gt;Fixed (e.g., SHA-256 = 256 bits)&lt;/td&gt;
&lt;td&gt;Variable (same length as input, roughly)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Primary goal&lt;/td&gt;
&lt;td&gt;Integrity &amp;amp; verification&lt;/td&gt;
&lt;td&gt;Confidentiality &amp;amp; secrecy&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Simple analogy:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Hashing is like a fingerprint—unique to a person, but you can’t reconstruct the person from a fingerprint. Encryption is like a locked diary—you can read it again once you unlock it with the key.&lt;/p&gt;
&lt;h2&gt;
  
  
  Practical Context
&lt;/h2&gt;

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

&lt;ul&gt;
&lt;li&gt;Storing passwords (never store them in plaintext).
&lt;/li&gt;
&lt;li&gt;Checking file integrity (e.g., confirming a download hasn’t been tampered with).
&lt;/li&gt;
&lt;li&gt;Creating digital signatures or detecting duplicate data.
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Transmitting sensitive data over a network (e.g., HTTPS, end-to-end chat).
&lt;/li&gt;
&lt;li&gt;Storing data that you need to access later in its original form (e.g., credit card numbers, personal messages).
&lt;/li&gt;
&lt;li&gt;Protecting files at rest that must be decrypted by authorized parties.
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Don’t hash passwords without salting&lt;/strong&gt;—plain hashes are vulnerable to rainbow tables.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don’t encrypt passwords&lt;/strong&gt;—if someone steals the key, all passwords are exposed.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don’t use encryption for integrity checks&lt;/strong&gt;—a tampered message can still be decrypted (it just looks like garbage).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don’t rely on hashing for confidentiality&lt;/strong&gt;—hashes are not secret; they’re deterministic and can be looked up.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Quick Example
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Storing a password (correct approach):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="c1"&gt;# Hashing (one-way) – store this in your database
&lt;/span&gt;&lt;span class="n"&gt;salt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urandom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my_secure_password&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;hash_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pbkdf2_hmac&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sha256&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Verification: re-compute with same salt and compare
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Encrypting a message (e.g., for sharing):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cryptography.fernet&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Fernet&lt;/span&gt;

&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Fernet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_key&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;cipher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Fernet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plaintext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sensitive meeting notes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;encrypted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cipher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# store or send this
&lt;/span&gt;
&lt;span class="c1"&gt;# Later, with the same key:
&lt;/span&gt;&lt;span class="n"&gt;decrypted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cipher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encrypted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# recovers original
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first snippet demonstrates &lt;strong&gt;irreversible hashing&lt;/strong&gt; for password storage—you never need the original password again, only to verify it. The second shows &lt;strong&gt;reversible encryption&lt;/strong&gt; for data you must retrieve later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Always pick the tool based on whether you need to recover the original data.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If you never need the original (passwords, integrity checks), use &lt;strong&gt;hashing&lt;/strong&gt; (with a salt). If you must get the original back (messages, files), use &lt;strong&gt;encryption&lt;/strong&gt; (and protect the key). Mix them up, and you’ll either leak secrets or lock yourself out.  &lt;/p&gt;

&lt;p&gt;For deeper diving, check out the OWASP guide on &lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html" rel="noopener noreferrer"&gt;Password Storage Cheat Sheet&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>hashingvsencryption</category>
      <category>passwordstorage</category>
      <category>dataintegrity</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Content Security Policy (CSP) : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Thu, 18 Jun 2026 14:00:30 +0000</pubDate>
      <link>https://dev.to/hongster85/content-security-policy-csp-understand-in-3-minutes-1554</link>
      <guid>https://dev.to/hongster85/content-security-policy-csp-understand-in-3-minutes-1554</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Content Security Policy (CSP)&lt;/strong&gt; is a browser security standard that tells your web application which sources of content (scripts, styles, images, etc.) are allowed to load and execute. You’ll run into CSP when a feature you deployed suddenly breaks in production—maybe a third‑party analytics script stops firing, or an inline &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; you added silently fails. The root cause? Your site’s CSP header is blocking it. If you’ve ever seen a console warning like “Refused to load the script because it violates the following Content Security Policy directive,” you’ve already met CSP.&lt;/p&gt;




&lt;h2&gt;
  
  
  Core Explanation
&lt;/h2&gt;

&lt;p&gt;Think of CSP as a &lt;strong&gt;bouncer at a club&lt;/strong&gt;. Your web page is the club, and every resource (JavaScript, CSS, images, fonts) is a guest. Without a bouncer, anyone can walk in—including malicious scripts injected via a cross‑site scripting (XSS) attack. CSP gives you a list of rules that the bouncer enforces: only guests from approved sources get in; everyone else is turned away.&lt;/p&gt;

&lt;p&gt;How does it work? You send a &lt;strong&gt;&lt;code&gt;Content-Security-Policy&lt;/code&gt; HTTP header&lt;/strong&gt; (or a &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tag) from your server. Inside that header you define &lt;strong&gt;directives&lt;/strong&gt; that specify allowed sources for different content types. The browser reads the policy and blocks any resource that doesn’t match.&lt;/p&gt;

&lt;p&gt;Key components (directives) you’ll see most often:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;default-src&lt;/code&gt;&lt;/strong&gt; — the fallback for any directive not explicitly set. If a resource type isn’t covered, the browser uses this.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;script-src&lt;/code&gt;&lt;/strong&gt; — controls which scripts can execute. This is the most common directive you’ll tweak.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;style-src&lt;/code&gt;&lt;/strong&gt; — controls which stylesheets and inline styles are allowed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;img-src&lt;/code&gt;&lt;/strong&gt; — controls image sources (often used to allow a CDN or data: URIs).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;connect-src&lt;/code&gt;&lt;/strong&gt; — controls which URLs your JavaScript can fetch via &lt;code&gt;fetch()&lt;/code&gt;, &lt;code&gt;XMLHttpRequest&lt;/code&gt;, WebSocket, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;report-uri&lt;/code&gt; / &lt;code&gt;report-to&lt;/code&gt;&lt;/strong&gt; — where the browser sends violation reports (useful for debugging).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A simple example directive set:&lt;br&gt;&lt;br&gt;
&lt;code&gt;default-src 'self'; script-src 'self' https://cdn.example.com; img-src *&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This says:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Everything defaults to only the same origin (&lt;code&gt;'self'&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;Scripts can come from the same origin &lt;strong&gt;or&lt;/strong&gt; from &lt;code&gt;https://cdn.example.com&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;Images can come from anywhere (&lt;code&gt;*&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CSP values can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Host sources&lt;/strong&gt; like &lt;code&gt;https://example.com&lt;/code&gt; or &lt;code&gt;*.example.com&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Schemes&lt;/strong&gt; like &lt;code&gt;https:&lt;/code&gt; or &lt;code&gt;data:&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;'self'&lt;/code&gt;&lt;/strong&gt; — matches the current origin.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;'none'&lt;/code&gt;&lt;/strong&gt; — blocks everything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;'unsafe-inline'&lt;/code&gt;&lt;/strong&gt; — allows inline code (use sparingly, because it weakens protection).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;'unsafe-eval'&lt;/code&gt;&lt;/strong&gt; — allows &lt;code&gt;eval()&lt;/code&gt; and similar functions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nonces or hashes&lt;/strong&gt; — for safely allowing specific inline scripts (modern best practice).&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Practical Context
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;When to use CSP:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Apply CSP on any public-facing web application that handles user input, stores session data, or embeds third‑party content. It’s your first line of defense against &lt;strong&gt;XSS attacks&lt;/strong&gt;. If you’re working on a banking app, an e‑commerce site, or a SaaS dashboard—you need CSP.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Very small static sites&lt;/strong&gt; with no user input and no third‑party scripts — the overhead might not be worth it.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;During development&lt;/strong&gt; if you’re actively debugging scripts that load from many untested sources. Better to start with a report-only policy first (using &lt;code&gt;Content-Security-Policy-Report-Only&lt;/code&gt; instead of the enforcement header).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If you rely heavily on inline event handlers&lt;/strong&gt; (like &lt;code&gt;onclick="..."&lt;/code&gt;) or &lt;code&gt;eval()&lt;/code&gt; in your code — CSP will block those unless you use &lt;code&gt;'unsafe-inline'&lt;/code&gt; or &lt;code&gt;'unsafe-eval'&lt;/code&gt;, but those weaken security. Consider refactoring.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Common real-world use cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;E‑commerce checkout&lt;/strong&gt; — prevent an injected script from stealing credit card data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SaaS dashboards&lt;/strong&gt; — allow analytics and A/B testing scripts from trusted CDNs while blocking everything else.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content management systems&lt;/strong&gt; — restrict what external resources editors can embed (e.g., images only from whitelisted image hosts).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Why should you care?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
XSS is still one of the most common web vulnerabilities. CSP makes it much harder for an attacker to inject malicious code, even if they find an injection point. It’s a defense-in-depth layer that browsers support universally. Plus, it’s required by many security compliance frameworks (OWASP Top 10, PCI DSS). Ignoring CSP means leaving your users’ browsers unprotected.&lt;/p&gt;


&lt;h2&gt;
  
  
  Quick Example
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Before CSP:&lt;/strong&gt; A page includes an inline &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; that sets a global variable, plus a third‑party analytics script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;12345&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://analytics.example.com/tracker.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After enforcing CSP&lt;/strong&gt; with this header:&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;Content-Security-Policy: default-src 'self'; script-src 'self' https://analytics.example.com;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The inline &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; block will be &lt;strong&gt;blocked&lt;/strong&gt; because &lt;code&gt;'unsafe-inline'&lt;/code&gt; is not allowed.
&lt;/li&gt;
&lt;li&gt;The analytics script from the whitelisted CDN will load normally.
&lt;/li&gt;
&lt;li&gt;Any attacker trying to inject &lt;code&gt;&amp;lt;script&amp;gt;malicious()&amp;lt;/script&amp;gt;&lt;/code&gt; will be blocked.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To fix the inline script, you’d replace it with an external JS file served from your own origin, or use a &lt;strong&gt;nonce&lt;/strong&gt; (e.g., &lt;code&gt;script-src 'nonce-abc123'&lt;/code&gt; and add &lt;code&gt;nonce="abc123"&lt;/code&gt; to the &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag). This example shows exactly why CSP forces you to audit and refactor your code—and why it’s so effective.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Start with a report-only CSP&lt;/strong&gt; and monitor violation reports before enforcing. This gives you a safe way to discover exactly what your site loads, without breaking anything. Once you have a clean report, switch to full enforcement. For deeper learning, read the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP" rel="noopener noreferrer"&gt;MDN CSP guide&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>contentsecuritypolicy</category>
      <category>websecurity</category>
      <category>xssprotection</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Graceful Shutdown : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Tue, 16 Jun 2026 14:00:35 +0000</pubDate>
      <link>https://dev.to/hongster85/graceful-shutdown-understand-in-3-minutes-1pgc</link>
      <guid>https://dev.to/hongster85/graceful-shutdown-understand-in-3-minutes-1pgc</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Graceful Shutdown&lt;/strong&gt; is the practice of letting your service finish its current work and clean up resources before the process actually stops. You need it because, in production, your service will be killed many times—during deployments, scaling events, or auto-recovery—and if it just drops dead, you lose in-flight requests, corrupt databases, and leave sockets open until the OS decides to clean them up. Every developer has seen the RST that kills a user’s payment, or the half-written file that corrupts a night’s worth of data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Explanation
&lt;/h2&gt;

&lt;p&gt;Graceful shutdown turns a sudden death into an orderly retirement. It works like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Listen for the termination signal.&lt;/strong&gt; Most orchestrators (Kubernetes, AWS, systemd) send &lt;code&gt;SIGTERM&lt;/code&gt; before they send &lt;code&gt;SIGKILL&lt;/code&gt;. Your process must catch that signal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stop accepting new work.&lt;/strong&gt; The server closes its listening socket or pauses its job queue. No new requests or tasks come in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drain in-flight work.&lt;/strong&gt; Ongoing requests finish within a reasonable deadline. Open database transactions commit or roll back. Files flush to disk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Release external resources.&lt;/strong&gt; Close connections to databases, message brokers, and caches. Unlink temporary files. Delete locks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exit cleanly.&lt;/strong&gt; Call &lt;code&gt;process.exit(0)&lt;/code&gt; or let the event loop finish naturally.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Think of it like closing a restaurant: you stop seating new customers, serve the ones already eating, clean the kitchen, lock the door, then walk away. A hard shutdown is flipping the breaker while the chef still has a knife in the air.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key components, simplified
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Signal handler&lt;/strong&gt; – the code that catches the OS’s “time to go” message.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drain period&lt;/strong&gt; – a timeout (e.g. 30 seconds) during which existing work is allowed to finish.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grace period&lt;/strong&gt; – the gap between &lt;code&gt;SIGTERM&lt;/code&gt; and &lt;code&gt;SIGKILL&lt;/code&gt; (usually configurable in your orchestrator).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Health check / readiness probe&lt;/strong&gt; – tells the load balancer to stop routing traffic before the service stops accepting connections.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The whole process is &lt;strong&gt;cooperative&lt;/strong&gt;: your service must volunteer to clean up; the OS won’t do it for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Context
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Use graceful shutdown whenever your service holds state or is in the middle of work that matters to users.&lt;/strong&gt; That includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Web servers (API, HTTP, gRPC)&lt;/li&gt;
&lt;li&gt;Background job workers (queue consumers, batch processors)&lt;/li&gt;
&lt;li&gt;Database connection pools, caches, and proxies&lt;/li&gt;
&lt;li&gt;Long-running CLI tools that should save progress&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Do not use graceful shutdown when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The service is a one-shot batch script. If it takes 2 seconds and fails, just restart it.&lt;/li&gt;
&lt;li&gt;You need an immediate, guaranteed kill for security or compliance reasons (e.g., a data scrubber that must stop &lt;em&gt;now&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;You’re running inside a sandbox that will be destroyed anyway (e.g., ephemeral CI containers that don’t need to save state).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Real‑world use cases
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Kubernetes pod termination&lt;/strong&gt; – K8s sends &lt;code&gt;SIGTERM&lt;/code&gt;, waits for the pod’s &lt;code&gt;terminationGracePeriodSeconds&lt;/code&gt;, then sends &lt;code&gt;SIGKILL&lt;/code&gt;. If your app doesn’t drain, users see 503s during rolling updates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Auto Scaling scale-in&lt;/strong&gt; – the EC2 instance gets a lifecycle hook. Without graceful handling, in-flight requests to that instance are lost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;database migration rollback&lt;/strong&gt; – interrupting a migration mid‑table can leave a partial schema. A signal handler can roll back the transaction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why should you care?&lt;/strong&gt; Because in distributed systems, every abrupt death shows up as latency spikes, data corruption, or support tickets. Graceful shutdown is the cheapest reliability improvement you can make—often just 10–15 lines of code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Example
&lt;/h2&gt;

&lt;p&gt;Below is a minimal Node.js HTTP server that implements graceful shutdown. The same pattern works in any language.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&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;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&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="o"&gt;=&amp;gt;&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="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Processing...&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="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Done&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// simulate slow work&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Start listening&lt;/span&gt;
&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Server on 3000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// Catch termination signals&lt;/span&gt;
&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SIGTERM&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SIGTERM received. Starting graceful shutdown...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Stop accepting new connections&lt;/span&gt;
  &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;All requests finished, exiting.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&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;p&gt;&lt;strong&gt;What this demonstrates:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The server runs normally. When the OS sends &lt;code&gt;SIGTERM&lt;/code&gt; (common from Kubernetes), it immediately stops listening. Any active requests (like the 5‑second timer) are allowed to finish before &lt;code&gt;process.exit(0)&lt;/code&gt; is called. Without the handler, the process would die mid‑request, causing a dropped connection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Implement graceful shutdown in every long‑running service that touches data or serves users.&lt;/strong&gt; It takes minutes to add, prevents hours of debugging, and is a baseline requirement for operating in modern container environments. For a deeper dive, read the &lt;a href="https://12factor.net/processes" rel="noopener noreferrer"&gt;Twelve‑Factor App process section&lt;/a&gt; on managing shutdown.&lt;/p&gt;

</description>
      <category>gracefulshutdown</category>
      <category>sigterm</category>
      <category>signalhandler</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Health Checks : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Thu, 11 Jun 2026 14:00:38 +0000</pubDate>
      <link>https://dev.to/hongster85/health-checks-understand-in-3-minutes-4l7e</link>
      <guid>https://dev.to/hongster85/health-checks-understand-in-3-minutes-4l7e</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;health check&lt;/strong&gt; is a lightweight endpoint or test that tells you whether your application is alive, ready to serve traffic, or dying a slow death. You’ve probably been woken up at 3 AM by an alert that your API is returning 500s, only to find it’s actually working fine – or worse, your load balancer kept sending requests to a zombie instance that was still accepting connections but returning garbage. Health checks exist to answer that simple question: “Is this thing actually working right now?” Without them, your system relies on guesswork, and your users are the first to know something is wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Explanation
&lt;/h2&gt;

&lt;p&gt;A health check is a dedicated, minimal path in your application (like &lt;code&gt;GET /health&lt;/code&gt;) that returns a quick status. It’s not a full regression test – just a heartbeat. Most health checks fall into two categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Liveness check&lt;/strong&gt;: “Is the process still running?” This prevents deadlocks or infinite loops from locking up your app. If it fails, the orchestrator (Kubernetes, for example) restarts the container.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Readiness check&lt;/strong&gt;: “Is the service ready to accept traffic?” This matters after startup or during heavy load when the app might be alive but not able to handle requests (e.g., still loading a cache or waiting for a database connection).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of it like a car’s check engine light. The light itself doesn’t tell you which cylinder is misfiring, but it tells you something is wrong before the engine seizes up. Health checks work the same way: they give you a binary signal – healthy or unhealthy – and leave deeper diagnostics for other tools.&lt;/p&gt;

&lt;p&gt;Key components of a well-designed health check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Minimal dependencies&lt;/strong&gt;: The health endpoint should only validate what’s truly critical (e.g., database connectivity, essential external APIs). If you check every service dependency, a cascading failure can make it look like your app is down when it’s actually fine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cached or short timeout&lt;/strong&gt;: Health checks run frequently – every few seconds. They must be fast (&amp;lt; 100ms ideally) and not block on long operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separation of concerns&lt;/strong&gt;: Liveness and readiness are separate endpoints. Mixing them can cause unnecessary restarts during startup delays.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The typical flow: load balancer or container orchestrator calls &lt;code&gt;GET /health&lt;/code&gt;. If it returns HTTP 200 with body &lt;code&gt;{"status":"ok"}&lt;/code&gt;, the service stays in rotation. If it returns 503 or times out, the orchestrator marks the instance as unhealthy and reroutes traffic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Context
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;When to use health checks&lt;/strong&gt;: Always. Any service that runs in production and is fronted by a load balancer or runs in an orchestrator (Docker Compose, Kubernetes, Nomad, etc.) benefits from health checks. Specifically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Microservices&lt;/strong&gt;: Each service should expose liveness and readiness endpoints so orchestration engines can manage lifecycle automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load-balanced APIs&lt;/strong&gt;: Cloud providers (AWS ALB, GCP LB, Nginx) can use health checks to stop sending traffic to failing instances.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database migrations&lt;/strong&gt;: A readiness check can delay traffic until migrations complete, avoiding race conditions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When NOT to use health checks&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Don’t make them do heavy work&lt;/strong&gt;, like running a full database query. That will degrade performance and cause false positives under load.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don’t use a single health check to test everything&lt;/strong&gt; – separate critical dependencies from nice-to-haves. If your app depends on an external analytics service that is temporarily down, the health check should still pass; the app can degrade gracefully.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don’t rely solely on health checks for monitoring&lt;/strong&gt; – they are for automated decision-making, not for deep troubleshooting. Use separate alerting for latency, error rates, and custom metrics.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why you should care: Health checks are the foundation of &lt;strong&gt;self-healing systems&lt;/strong&gt;. They let your infrastructure automatically restart dead instances, drain traffic from slow ones, and gradually roll out new versions. Without them, you’re running a fire-fighting operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Example
&lt;/h2&gt;

&lt;p&gt;Here’s a minimal health check in a Node.js Express app:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Readiness check – also checks DB connectivity&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;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/ready&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &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="o"&gt;=&amp;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="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;ping&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// lightweight check&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ready&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;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="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;503&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;not ready&lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;err&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="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Liveness check – just returns 200 if process is running&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;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/live&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;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="o"&gt;=&amp;gt;&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="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alive&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this demonstrates: The &lt;code&gt;/live&lt;/code&gt; endpoint is a simple “I’m still running” signal. The &lt;code&gt;/ready&lt;/code&gt; endpoint also verifies database connectivity. In a Kubernetes &lt;code&gt;Deployment&lt;/code&gt;, you’d point &lt;code&gt;livenessProbe&lt;/code&gt; to &lt;code&gt;/live&lt;/code&gt; and &lt;code&gt;readinessProbe&lt;/code&gt; to &lt;code&gt;/ready&lt;/code&gt;. This separation prevents the orchestrator from restarting your container every time the DB has a hiccup (liveness stays green), while still stopping new traffic during a real outage (readiness goes red).&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Always implement separate liveness and readiness endpoints&lt;/strong&gt; that are fast, minimal, and only check what truly matters for traffic acceptance. This single pattern will make your deployments safer, your debugging easier, and your nights quieter. For deeper reading, check out the Kubernetes documentation on &lt;a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/" rel="noopener noreferrer"&gt;Configure Liveness, Readiness and Startup Probes&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>healthcheck</category>
      <category>livenessprobe</category>
      <category>readinessprobe</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>API Gateway : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Tue, 09 Jun 2026 14:00:24 +0000</pubDate>
      <link>https://dev.to/hongster85/api-gateway-understand-in-3-minutes-4aia</link>
      <guid>https://dev.to/hongster85/api-gateway-understand-in-3-minutes-4aia</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;An &lt;strong&gt;API Gateway&lt;/strong&gt; is a single entry point that sits between your clients and your backend services, routing requests, handling cross-cutting concerns, and shielding your internal architecture from the outside world. You’ve probably felt the pain of managing authentication, rate limiting, and request logging across dozens of microservices – or watched your frontend code balloon with URLs for every service. That’s when you need a gatekeeper to unify, protect, and simplify your API layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Explanation
&lt;/h2&gt;

&lt;p&gt;Think of an API Gateway like a hotel concierge. You (the client) walk in and ask for dinner reservations. The concierge doesn’t cook – they know exactly which restaurant to call, handle the booking, translate your request, and hand you a confirmation. You never need to know the chef’s phone number or the kitchen layout.&lt;/p&gt;

&lt;p&gt;In technical terms, the API Gateway acts as a reverse proxy that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Routes requests&lt;/strong&gt; to the correct backend service (e.g., &lt;code&gt;/users&lt;/code&gt; → User Service, &lt;code&gt;/orders&lt;/code&gt; → Order Service).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authenticates and authorizes&lt;/strong&gt; – checks tokens, API keys, or OAuth before traffic reaches your services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate limits and throttles&lt;/strong&gt; – prevents abuse by capping requests per client.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aggregates responses&lt;/strong&gt; – if a page needs data from three services, the gateway calls them in parallel and merges the results for the client.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transforms protocols&lt;/strong&gt; – accepts HTTP/REST from clients and translates to gRPC or WebSocket internally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handles cross-cutting concerns&lt;/strong&gt; – logging, metrics, caching, and request/response modification in one place.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your microservices stay focused on business logic. The gateway owns the “edge” concerns.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Context
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;When to use an API Gateway:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have &lt;strong&gt;multiple microservices&lt;/strong&gt; that need a unified API surface for mobile apps, web UIs, or third-party integrations.&lt;/li&gt;
&lt;li&gt;You need &lt;strong&gt;centralized security&lt;/strong&gt; – a single place to enforce authentication, SSL termination, or IP whitelisting.&lt;/li&gt;
&lt;li&gt;You want to &lt;strong&gt;decouple clients from service evolution&lt;/strong&gt; – change backend URLs or split a service without updating every client.&lt;/li&gt;
&lt;li&gt;You’re dealing with &lt;strong&gt;cross-cutting policies&lt;/strong&gt; like rate limiting, caching, or request logging that would otherwise be duplicated.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When NOT to use an API Gateway:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have a &lt;strong&gt;simple monolithic app&lt;/strong&gt; – adding a gateway is unnecessary overhead.&lt;/li&gt;
&lt;li&gt;Your latency requirements are &lt;strong&gt;ultra-low&lt;/strong&gt; – an extra hop can add milliseconds that matter in real-time systems.&lt;/li&gt;
&lt;li&gt;Your team is &lt;strong&gt;small and moving fast&lt;/strong&gt; – the gateway introduces operational complexity (deployment, monitoring, config management) that might outweigh benefits early on.&lt;/li&gt;
&lt;li&gt;You need &lt;strong&gt;fine-grained per-service policies&lt;/strong&gt; – some gateways force a one-size-fits-all approach; if each service has unique auth or throttling needs, the gateway can become a bottleneck.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why you should care:&lt;/strong&gt; Without a gateway, your clients become tightly coupled to your internal service topology. Any change can break apps. With a gateway, you gain a control point for security, observability, and evolution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Example
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Before (no gateway):&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Mobile app calls &lt;code&gt;https://api.example.com/users/profile&lt;/code&gt; (User Service), then separately calls &lt;code&gt;https://orders.example.com/orders&lt;/code&gt; (Order Service). Client code knows exact service URLs, handles auth tokens, and deals with different error formats.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After (with gateway):&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Mobile app calls only &lt;code&gt;https://api.example.com/v1/get-dashboard&lt;/code&gt;. The API Gateway:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Authenticates the token.&lt;/li&gt;
&lt;li&gt;Calls User Service for profile data and Order Service for recent orders (in parallel).&lt;/li&gt;
&lt;li&gt;Merges the two responses into a single JSON payload.&lt;/li&gt;
&lt;li&gt;Returns it to the app.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The client code is simpler, and you can swap the Order Service URL without updating the mobile app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Don’t let clients map to individual services – use an API Gateway to own the edge and keep your architecture flexible.&lt;/strong&gt; For deeper exploration, check out Martin Fowler’s article on the “API Gateway” pattern (a quick search will find it). You now have the 3-minute baseline to decide if it fits your next project.&lt;/p&gt;

</description>
      <category>apigateway</category>
      <category>microservices</category>
      <category>reverseproxy</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Pub/Sub Pattern : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Thu, 04 Jun 2026 14:00:24 +0000</pubDate>
      <link>https://dev.to/hongster85/pubsub-pattern-understand-in-3-minutes-3c2i</link>
      <guid>https://dev.to/hongster85/pubsub-pattern-understand-in-3-minutes-3c2i</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Pub/Sub (Publish/Subscribe) pattern&lt;/strong&gt; is a messaging architecture where senders (publishers) broadcast messages without knowing who will receive them, and receivers (subscribers) listen for messages without knowing who sent them. You encounter this need when your application grows beyond a single process: a user signs up and you need to notify the email service, analytics pipeline, and CRM system—all independently. Without Pub/Sub, you end up with tangled, synchronous calls that break if one service is slow or down. This pattern lets components evolve independently while staying loosely coupled.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Explanation
&lt;/h2&gt;

&lt;p&gt;Pub/Sub works through a central &lt;strong&gt;message broker&lt;/strong&gt; (or event bus) that sits between publishers and subscribers. Here’s how it flows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Publisher&lt;/strong&gt; sends a message (event) to the broker, labeling it with a &lt;strong&gt;topic&lt;/strong&gt; (e.g., “user.signed_up”).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Broker&lt;/strong&gt; receives the message and stores it (optionally) and immediately routes copies to every subscriber that has expressed interest in that topic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subscriber&lt;/strong&gt; receives the message and processes it—sending an email, updating a dashboard, etc.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Key components at a glance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Topic / Channel&lt;/strong&gt; – A named logical category for events. Publishers write to topics; subscribers read from them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Publisher&lt;/strong&gt; – The component that emits events. It has zero knowledge of who is listening.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subscriber&lt;/strong&gt; – The component that consumes events. It receives all messages published on its subscribed topics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Broker&lt;/strong&gt; – The middleware that handles message delivery, filtering, fan-out, and often durability (ensuring messages aren’t lost if a subscriber is offline).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Analogy&lt;/strong&gt;: Think of a radio station. The station (publisher) broadcasts music on a specific frequency (topic). Anyone with a receiver tuned to that frequency (subscriber) hears the music. The station doesn’t know who is listening, and listeners don’t know the station’s internal operations. If a new listener tunes in late, they only hear from that moment onward (unless the radio station records the broadcast, like a broker with message persistence).&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Context
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;When to use Pub/Sub:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need to &lt;strong&gt;decouple&lt;/strong&gt; components that depend on the same event. Example: a new order placed should trigger inventory update, payment processing, and shipment scheduling.&lt;/li&gt;
&lt;li&gt;You have &lt;strong&gt;multiple independent consumers&lt;/strong&gt; that each need the same event, but they shouldn’t wait for each other.&lt;/li&gt;
&lt;li&gt;You want &lt;strong&gt;scalable fan-out&lt;/strong&gt;: one event, many receivers, without tight point-to-point connections.&lt;/li&gt;
&lt;li&gt;You need &lt;strong&gt;event-driven architecture&lt;/strong&gt; where services react to changes asynchronously.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When NOT to use Pub/Sub:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need &lt;strong&gt;guaranteed point-to-point&lt;/strong&gt; delivery to exactly one consumer (use a queue instead, like with message queues or task workers).&lt;/li&gt;
&lt;li&gt;Your requirements are &lt;strong&gt;synchronous and low-latency&lt;/strong&gt; (e.g., a user clicks “pay” and expects immediate response). Pub/Sub introduces asynchronous overhead.&lt;/li&gt;
&lt;li&gt;You have &lt;strong&gt;simple, one-to-one&lt;/strong&gt; communication that doesn’t need extra infrastructure (a direct function call is simpler).&lt;/li&gt;
&lt;li&gt;You cannot tolerate &lt;strong&gt;event ordering guarantees&lt;/strong&gt; (most Pub/Sub brokers don’t guarantee strict order across multiple subscribers; you may need a dedicated queue per consumer).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why you should care:&lt;/strong&gt; Pub/Sub is the foundation of microservices, serverless applications, and real-time data pipelines. If you’ve ever needed to add a new feature that reacts to an existing event without rewriting existing code, Pub/Sub saves you from coupling hell.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Example
&lt;/h2&gt;

&lt;p&gt;Here’s a minimal Node.js example using a simple in-process event emitter (conceptually same as a broker):&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;EventEmitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;events&lt;/span&gt;&lt;span class="dl"&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;broker&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;EventEmitter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Subscriber 1: send welcome email&lt;/span&gt;
&lt;span class="nx"&gt;broker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user.signed_up&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;user&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Email: Welcome &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;// Subscriber 2: track analytics&lt;/span&gt;
&lt;span class="nx"&gt;broker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user.signed_up&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;user&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Analytics: New signup from &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;// Publisher: emit event&lt;/span&gt;
&lt;span class="nx"&gt;broker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user.signed_up&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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alice@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// Output (order may vary):&lt;/span&gt;
&lt;span class="c1"&gt;// Email: Welcome Alice!&lt;/span&gt;
&lt;span class="c1"&gt;// Analytics: New signup from alice@example.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What this demonstrates:&lt;/strong&gt; The publisher (the &lt;code&gt;emit&lt;/code&gt; call) doesn’t know or care about the subscribers. Both subscribers react independently. Adding a third subscriber (e.g., “send SMS”) requires zero changes to the publisher—just add another &lt;code&gt;broker.on(...)&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Pub/Sub is the cleanest way to decouple event producers from multiple event consumers.&lt;/strong&gt; Whenever you find yourself writing code that says “after X, notify Y and Z,” consider whether a Pub/Sub broker could let X, Y, and Z evolve independently. For deeper dives, check out the concept of &lt;strong&gt;event-driven architecture&lt;/strong&gt; and brokers like Redis Pub/Sub, NATS, or cloud services like AWS SNS.&lt;/p&gt;

</description>
      <category>pubsubpattern</category>
      <category>messagebroker</category>
      <category>eventdrivenarchitecture</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Message Queues : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Tue, 02 Jun 2026 14:00:27 +0000</pubDate>
      <link>https://dev.to/hongster85/message-queues-understand-in-3-minutes-2pbi</link>
      <guid>https://dev.to/hongster85/message-queues-understand-in-3-minutes-2pbi</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;Message Queue&lt;/strong&gt; is a system that lets one part of your application send a piece of work to another part without waiting for an immediate reply. You run into this need when your app starts choking on tasks that don’t need to happen right now—like sending a confirmation email, resizing an image, or syncing data to a third-party API. If you’ve ever had a request handler take seconds to finish because it was waiting on a slow external service, you’ve already wished you had a queue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Explanation
&lt;/h2&gt;

&lt;p&gt;Think of a message queue as a buffer between two parts of your system. It works with three simple components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Producer&lt;/strong&gt; – the part that creates a message (a unit of work).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Queue&lt;/strong&gt; – an inbox where messages wait in order.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consumer&lt;/strong&gt; – the part that picks up and processes messages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s how it flows: Your producer sends a message into the queue and immediately moves on to other work. The consumer (often running in a separate process or server) pulls messages from the queue at its own pace, processes them, and acknowledges completion. If the consumer fails, the message stays in the queue for retry.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analogy&lt;/strong&gt;: Imagine a busy restaurant. The waiter takes orders (producer) and drops them on a counter (queue). The cook (consumer) picks orders one by one, prepares the food, and moves to the next. The waiter doesn’t wait for the cook; they take the next table’s order right away. The restaurant doesn’t collapse if the cook slows down—orders just pile up on the counter.&lt;/p&gt;

&lt;p&gt;This decoupling is the magic. It lets you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handle traffic spikes gracefully (messages queue up, nothing is lost).&lt;/li&gt;
&lt;li&gt;Scale consumers independently (add more cooks when the dinner rush hits).&lt;/li&gt;
&lt;li&gt;Recover from failures without data loss (messages persist until processed).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The queue guarantees delivery: once a message is accepted, the system ensures it will eventually be processed—even if a consumer crashes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Context
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;When to use a message queue:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need to &lt;strong&gt;decouple&lt;/strong&gt; two services (e.g., a web app and a background job processor).&lt;/li&gt;
&lt;li&gt;You have &lt;strong&gt;bursty traffic&lt;/strong&gt;—your system should absorb sudden load without slowing down user-facing responses.&lt;/li&gt;
&lt;li&gt;You want to &lt;strong&gt;process tasks asynchronously&lt;/strong&gt; (sending emails, generating PDFs, calling external APIs).&lt;/li&gt;
&lt;li&gt;Real-world use cases:

&lt;ul&gt;
&lt;li&gt;Order fulfillment (place order → queue work for inventory, payment, shipping)&lt;/li&gt;
&lt;li&gt;Log aggregation (multiple services send log entries to a central queue)&lt;/li&gt;
&lt;li&gt;Image/video processing (user uploads → queue thumbnails, transcoding)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When NOT to use a message queue:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your operation needs a real-time, synchronous response (e.g., a user login check).&lt;/li&gt;
&lt;li&gt;You have a simple request-reply pattern with no need for durability or retries.&lt;/li&gt;
&lt;li&gt;You’re adding more complexity than necessary—queues introduce operational overhead (monitoring, storage, potential backpressure).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why should you care?&lt;/strong&gt; Without a queue, your system becomes tightly coupled: a slow downstream service slows your frontend, and failures cascade. With a queue, you gain resilience, scalability, and the freedom to evolve components independently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Example
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Before (synchronous):&lt;/strong&gt; A user signs up. The registration handler sends a welcome email and waits for the SMTP server to respond. Response time: 1.5 seconds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register_user&lt;/span&gt;&lt;span class="p"&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;send_welcome_email&lt;/span&gt;&lt;span class="p"&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;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# blocks here
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&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;ok&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;p&gt;&lt;strong&gt;After (with a message queue):&lt;/strong&gt; The handler only enqueues a message and returns immediately. A separate background worker picks it up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Producer (in the web app)
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register_user&lt;/span&gt;&lt;span class="p"&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&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;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enqueue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;send_welcome_email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&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;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# returns instantly
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&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;ok&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Consumer (separate worker process)
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;send_welcome_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The user sees the response in milliseconds. The email is sent eventually. If the worker crashes, the message stays in the queue and gets retried.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Use a message queue whenever you want to decouple work that doesn’t need immediate feedback.&lt;/strong&gt; It turns fragile, synchronous dependencies into resilient, asynchronous pipelines. For deeper learning, start with the official docs of &lt;strong&gt;RabbitMQ&lt;/strong&gt; or &lt;strong&gt;Redis Pub/Sub&lt;/strong&gt;—both are battle-tested and well-documented.&lt;/p&gt;

</description>
      <category>messagequeue</category>
      <category>asynchronousprocessing</category>
      <category>decoupleservices</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Kubernetes Basics : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Thu, 28 May 2026 14:00:25 +0000</pubDate>
      <link>https://dev.to/hongster85/kubernetes-basics-understand-in-3-minutes-11of</link>
      <guid>https://dev.to/hongster85/kubernetes-basics-understand-in-3-minutes-11of</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Kubernetes Basics&lt;/strong&gt; is a system for automating the deployment, scaling, and management of containerized applications—but you probably care about it because your team's microservices are growing faster than your patience for manually restarting crashed containers. You’ve heard it’s the industry standard for running containers in production, yet the terminology (“pods,” “nodes,” “clusters”) sounds like a sci-fi movie. If you’ve ever deployed a container with Docker Compose and then asked yourself, “what happens when one of these services goes down at 3 AM?”—you need Kubernetes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Explanation
&lt;/h2&gt;

&lt;p&gt;Kubernetes (often called &lt;strong&gt;K8s&lt;/strong&gt;) is like an automated hotel manager for your containers. You give it a specification for how many containers should run, how much CPU and memory they need, and which ports they expose. K8s then finds the right machines (called &lt;strong&gt;nodes&lt;/strong&gt;) to place them on, keeps them healthy, and handles networking so services can talk to each other.&lt;/p&gt;

&lt;p&gt;Here’s how it works in three simple layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cluster&lt;/strong&gt; – The full hotel: a set of machines (nodes) that Kubernetes manages. One machine is the &lt;strong&gt;control plane&lt;/strong&gt; (the manager), the rest are &lt;strong&gt;workers&lt;/strong&gt; (the rooms where containers actually run).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pod&lt;/strong&gt; – The smallest deployable unit: one or more containers that share storage and network. Think of a pod as a room with one guest (container) or a couple of guests that need to share the same space. Most of the time, you run one container per pod.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment&lt;/strong&gt; – A declarative blueprint that tells Kubernetes “I want three copies of this pod, always running.” If a pod crashes, Kubernetes creates a new one automatically. You don’t restart containers—you let the system reconcile the desired state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A simple analogy: imagine you’re running a photo‑sharing app with a web server, a database, and a cache. Without Kubernetes, you manually SSH into a server, start Docker containers, and pray they don’t die. With Kubernetes, you write a YAML file describing each service (e.g., “run 2 copies of web‑server, each with 512 MB RAM, and expose port 80”). Kubernetes handles placement, health checks, scaling, and even rolling updates with zero downtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Context
&lt;/h2&gt;

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

&lt;ul&gt;
&lt;li&gt;You have multiple microservices that need to be deployed, scaled, and updated independently.&lt;/li&gt;
&lt;li&gt;Your application experiences variable traffic—you want to automatically scale containers up and down.&lt;/li&gt;
&lt;li&gt;You need high availability: a failed node should not take down your service (Kubernetes reschedules pods onto healthy nodes automatically).&lt;/li&gt;
&lt;li&gt;You already use containers (Docker/containerd) and want a production‑grade orchestration layer.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;You’re running a single monolithic application with no scaling needs—a single Docker container on a VM is simpler and cheaper.&lt;/li&gt;
&lt;li&gt;Your team lacks operational experience with containers and networking—Kubernetes adds complexity (networking, storage, security) that can overwhelm small teams.&lt;/li&gt;
&lt;li&gt;You need a quick prototype—stick to Docker Compose or a platform‑as‑a‑service (e.g., Heroku) until your architecture matures.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Common real‑world use cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD pipelines&lt;/strong&gt; – Running integration tests in isolated pods, then rolling out new versions with zero downtime.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Microservices platforms&lt;/strong&gt; – Spotify, Pinterest, and hundreds of companies run thousands of services, each with independent scaling and updates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch processing&lt;/strong&gt; – Spinning up hundreds of pods to process data, then tearing them down when done.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick Example
&lt;/h2&gt;

&lt;p&gt;Here’s a minimal Kubernetes &lt;strong&gt;Deployment&lt;/strong&gt; YAML for a simple web server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;web-server&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;web&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;web&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:1.25&lt;/span&gt;
        &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this does: It declares that you want three copies (&lt;code&gt;replicas: 3&lt;/code&gt;) of a pod running the &lt;code&gt;nginx:1.25&lt;/code&gt; container, listening on port 80. When you apply this YAML (&lt;code&gt;kubectl apply -f deploy.yaml&lt;/code&gt;), Kubernetes ensures exactly three healthy pods exist at all times. If a node fails, it recreates the missing pods elsewhere. No manual restarts, no “oh, one of my containers died.”&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Kubernetes treats your infrastructure as programmable—write a declarative spec, and the system automates the “keeping it running” part.&lt;/strong&gt; Start with a single deployment, and you’ll immediately grasp why it’s the defacto standard for container orchestration. For deeper learning, check out the official interactive tutorial at &lt;a href="https://kubernetes.io/docs/tutorials/" rel="noopener noreferrer"&gt;Kubernetes.io/docs/tutorials&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>containerorchestration</category>
      <category>microservices</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Critical Rendering Path : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Tue, 26 May 2026 14:00:26 +0000</pubDate>
      <link>https://dev.to/hongster85/critical-rendering-path-understand-in-3-minutes-cd</link>
      <guid>https://dev.to/hongster85/critical-rendering-path-understand-in-3-minutes-cd</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Critical Rendering Path&lt;/strong&gt; is the sequence of steps the browser takes to convert HTML, CSS, and JavaScript into pixels on the screen—and the reason your site feels sluggish, even if your code is “correct,” is that every byte you send forces the browser through this pipeline, often blocking the user from seeing anything useful.&lt;/p&gt;

&lt;p&gt;You’ve shipped a fast backend, optimized database queries, and minimized assets, yet the page still takes a second to load. The culprit? The browser can’t paint a single pixel until it finishes parsing, styling, and laying out the page. Understanding the Critical Rendering Path helps you identify exactly which step is causing the delay and what to do about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Explanation
&lt;/h2&gt;

&lt;p&gt;Think of the Critical Rendering Path like an assembly line in a factory. The browser starts with raw materials (your HTML and CSS), processes each piece step-by-step, and finally outputs a finished product (the visible page). If any station is slow, the entire line stalls.&lt;/p&gt;

&lt;p&gt;Here are the key steps in order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;DOM (Document Object Model) construction&lt;/strong&gt; – The browser reads HTML and creates a tree of elements. Every &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; becomes a node. This step is blocked until all HTML is parsed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSSOM (CSS Object Model) construction&lt;/strong&gt; – The browser reads CSS (inline, &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt;, or linked files) and builds a separate tree of style rules. This step blocks rendering because the browser won’t paint anything until it knows the final styles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Render Tree construction&lt;/strong&gt; – The browser combines the DOM and CSSOM into a single tree of visible elements. Hidden nodes (&lt;code&gt;display: none&lt;/code&gt;) are excluded.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Layout&lt;/strong&gt; – The browser calculates the exact position and size of each visible element on the page. This is where you pay for complex CSS (e.g., floats, grids, large tables).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Paint&lt;/strong&gt; – The browser fills in pixels: text, colors, images, borders. It rasterizes the render tree into actual visual layers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Composite&lt;/strong&gt; – The browser combines all painted layers into the final screen image. This step is where transparency, transforms, and &lt;code&gt;opacity&lt;/code&gt; are resolved.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Key insight:&lt;/strong&gt; JavaScript can block both DOM and CSSOM construction if it appears before style or script tags that modify the DOM. By default, &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags pause the assembly line until the script is fetched and executed.&lt;/p&gt;

&lt;p&gt;The “critical” part refers to the initial paint—the first time the user sees anything. If you can minimize or reorder the steps before that first paint, your page feels instant.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Context
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;When to use the Critical Rendering Path:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You’re optimizing page load time for a public-facing site (e.g., landing page, e-commerce product page).
&lt;/li&gt;
&lt;li&gt;You’re debugging why a page flashes a white screen for hundreds of milliseconds.
&lt;/li&gt;
&lt;li&gt;You’re measuring performance with tools like Lighthouse or WebPageTest and see high “Render-Blocking Resources” or “Largest Contentful Paint (LCP)” scores.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When &lt;em&gt;not&lt;/em&gt; to focus on it:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your app is an internal tool where users accept moderate load times (e.g., a CI dashboard).
&lt;/li&gt;
&lt;li&gt;You’re working on a single-page app that loads once and then navigates via JavaScript (the initial load still matters, but subsequent renders follow a different path).
&lt;/li&gt;
&lt;li&gt;Your bottleneck is clearly on the server side (latency, large images, unoptimized API calls)—fix those first.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Real-world use cases:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deferring non-critical CSS using &lt;code&gt;media="print"&lt;/code&gt; or &lt;code&gt;rel="preload"&lt;/code&gt; so the browser doesn’t wait for it to paint.
&lt;/li&gt;
&lt;li&gt;Inlining critical CSS (the styles needed above the fold) into &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; to avoid an extra request.
&lt;/li&gt;
&lt;li&gt;Adding &lt;code&gt;defer&lt;/code&gt; or &lt;code&gt;async&lt;/code&gt; to &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags to prevent them from blocking DOM and CSSOM construction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why you should care:&lt;/strong&gt; Even a 0.5-second improvement in initial paint can boost conversion rates by 10–20% on e-commerce sites. Users expect pages to be interactive in under 2 seconds, and the Critical Rendering Path is the ultimate gatekeeper.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Example
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Before (blocking script blocks paint):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"styles.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello World&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"analytics.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Welcome to the site.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the browser downloads &lt;code&gt;styles.css&lt;/code&gt;, then parses HTML until it hits &lt;code&gt;analytics.js&lt;/code&gt;. It stops to fetch and execute the script (which might modify the DOM or CSSOM). Only after that does it continue parsing and painting. The user waits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After (defer non-blocking script):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"styles.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello World&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Welcome to the site.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"analytics.js"&lt;/span&gt; &lt;span class="na"&gt;defer&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By moving the script to the bottom and adding &lt;code&gt;defer&lt;/code&gt;, the browser can finish parsing, build the render tree, and paint the first frame before the script ever runs. The user sees “Hello World” immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this demonstrates:&lt;/strong&gt; The position and attribute of a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag directly controls how much the Critical Rendering Path is blocked. Small changes make big performance differences.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Optimize the Critical Rendering Path by prioritizing the order in which you load HTML, CSS, and JavaScript—reduce blocking resources above the fold, and let everything else load asynchronously.&lt;/strong&gt; For a deeper dive, read Google’s web.dev article on &lt;a href="https://web.dev/critical-rendering-path/" rel="noopener noreferrer"&gt;Critical Rendering Path&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>criticalrenderingpath</category>
      <category>renderblockingresources</category>
      <category>largestcontentfulpaint</category>
      <category>abotwrotethis</category>
    </item>
  </channel>
</rss>
