<?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>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>
    <item>
      <title>Intersection Observer API : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Thu, 21 May 2026 14:00:26 +0000</pubDate>
      <link>https://dev.to/hongster85/intersection-observer-api-understand-in-3-minutes-abk</link>
      <guid>https://dev.to/hongster85/intersection-observer-api-understand-in-3-minutes-abk</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Intersection Observer API&lt;/strong&gt; lets you efficiently detect when an element enters or leaves the viewport (or another parent element). You need this because the old way—listening to scroll events and manually calculating positions—is slow, janky, and wastes battery life on mobile devices. Every time you've built an infinite scroll, lazy-loaded images, or a “when do I animate this?” feature, you've probably either suffered scroll-performance pain or written hacky throttled code. The Intersection Observer gives you a clean, performant, browser-native solution.&lt;/p&gt;

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

&lt;p&gt;Think of it as a surveillance camera for your webpage. You give the camera (the observer) a target element and say, “Tell me the moment this box enters or leaves the screen (or any other container).” The browser handles the math for you—no manual scroll listeners, no &lt;code&gt;getBoundingClientRect()&lt;/code&gt; in a loop.&lt;/p&gt;

&lt;p&gt;Here’s how the core pieces fit together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Observer&lt;/strong&gt;: You create one instance of &lt;code&gt;IntersectionObserver&lt;/code&gt;. It’s your watchtower.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Callback&lt;/strong&gt;: You pass a function that fires every time the &lt;strong&gt;visibility&lt;/strong&gt; of any observed element changes. The callback receives an array of &lt;code&gt;IntersectionObserverEntry&lt;/code&gt; objects—one per observed element that changed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Thresholds&lt;/strong&gt;: You tell the observer &lt;em&gt;how much&lt;/em&gt; of the element must be visible before it triggers. A single number like &lt;code&gt;0.5&lt;/code&gt; means “fire when at least 50% of the element is visible.” You can also pass an array like &lt;code&gt;[0, 0.25, 0.5, 0.75, 1]&lt;/code&gt; for multiple checkpoints.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Root&lt;/strong&gt;: By default, the observer checks against the browser viewport. But you can set a custom &lt;strong&gt;root&lt;/strong&gt;—any scrollable container—so you can track visibility inside a scrollable div.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Root Margin&lt;/strong&gt;: Think of it as a buffer zone around the root. Use &lt;code&gt;rootMargin: "100px"&lt;/code&gt; to trigger the callback when the element is &lt;em&gt;100 pixels&lt;/em&gt; outside the viewport—useful for pre-loading content before the user scrolls to it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The magic? The browser runs this in a separate, optimized thread. No blocking main-thread work. Your callback fires only when the intersection state actually changes, not on every pixel scroll.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;When to use the Intersection Observer API:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lazy-loading images or iframes&lt;/strong&gt;: Only fetch the resource when the element is close to entering the viewport. Combine with &lt;code&gt;rootMargin&lt;/code&gt; to start loading early.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infinite scrolling&lt;/strong&gt;: Detect when a sentinel element (a small invisible div at the bottom of a list) becomes visible, then append more items. Much cleaner than scroll-event hacks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ads or analytics&lt;/strong&gt;: Track how long an element was visible or when a user first saw an ad unit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Animations on scroll&lt;/strong&gt;: Trigger a CSS transition or class change when an element enters the viewport. Great for “scroll-triggered fade-ins.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sticky or fixed positioning&lt;/strong&gt;: Know exactly when an element stops being visible and swap to a fixed position.&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;
&lt;strong&gt;If you need to know the element’s exact X/Y position&lt;/strong&gt; (use &lt;code&gt;getBoundingClientRect()&lt;/code&gt; or &lt;code&gt;ResizeObserver&lt;/code&gt;). Intersection Observer only tells you “it’s intersecting” or “it’s not.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If you’re building a parallax effect that needs pixel-level scroll offsets&lt;/strong&gt;. The callback doesn’t fire continuously—only at threshold crossings. For smooth parallax, a scroll-based approach is still better (but use &lt;code&gt;requestAnimationFrame&lt;/code&gt; to throttle).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If you need real-time tracking of visibility percentage&lt;/strong&gt; (e.g., a progress bar showing how much of an article is read). You can approximate it with many thresholds, but it’s not a continuous stream.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why should you care? Because it turns a notoriously expensive, error-prone task into a handful of lines that run in low overhead. Your users get smoother scrolling, your app uses less CPU, and your code becomes more declarative.&lt;/p&gt;

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

&lt;p&gt;Here’s how to lazy-load an image when it enters the viewport:&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;observer&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;IntersectionObserver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entries&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;entries&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;entry&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isIntersecting&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// swap placeholder for real URL&lt;/span&gt;
        &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unobserve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;     &lt;span class="c1"&gt;// stop watching after load&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;rootMargin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;200px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;           &lt;span class="c1"&gt;// start loading 200px before visible&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.lazy-image&lt;/span&gt;&lt;span class="dl"&gt;"&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;img&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;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What’s happening? We create an observer that fires when a watched element intersects. Inside the callback, we check &lt;code&gt;entry.isIntersecting&lt;/code&gt;. If true, we set the real &lt;code&gt;src&lt;/code&gt; (stored in a &lt;code&gt;data-src&lt;/code&gt; attribute) and then stop observing that element so we don’t re-trigger. The &lt;code&gt;rootMargin&lt;/code&gt; gives us a head start so images load just before the user scrolls to them. No scroll listener, no &lt;code&gt;getBoundingClientRect()&lt;/code&gt;—the browser does the heavy lifting.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Stop listening to scroll events for visibility checks—let the browser do it for you.&lt;/strong&gt; The Intersection Observer API is the standard, performant way to know when an element appears or disappears from a container. For a deeper dive, read the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API" rel="noopener noreferrer"&gt;MDN documentation on Intersection Observer&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>intersectionobserver</category>
      <category>lazyloading</category>
      <category>scrollanimation</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Web Workers : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Tue, 19 May 2026 14:00:27 +0000</pubDate>
      <link>https://dev.to/hongster85/web-workers-understand-in-3-minutes-5gb9</link>
      <guid>https://dev.to/hongster85/web-workers-understand-in-3-minutes-5gb9</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Web Workers&lt;/strong&gt; let you run JavaScript in the background, on a separate thread, so your main page stays responsive. Have you ever clicked a button on a web app and watched the whole page freeze while some heavy logic runs? Or felt that annoying lag while a large dataset gets processed? That frozen feeling happens because JavaScript normally runs everything—UI updates, click handlers, data crunching—on a single thread. Web Workers fix this by handing off the heavy lifting to a background helper, leaving the main thread free to handle user interactions smoothly.&lt;/p&gt;

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

&lt;p&gt;Think of your browser tab as a single-lane road. Without Web Workers, every task—rendering a button, parsing a JSON file, animating a chart—has to wait in the same lane. If one task takes too long (say, processing 10,000 records), everything else stalls.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;Web Worker&lt;/strong&gt; is like a parallel service lane. You send work to it, it does the job independently, and then it sends the result back. Meanwhile, your main lane keeps flowing with user interactions, animations, and DOM updates.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You create a Worker&lt;/strong&gt; by pointing it to a separate JavaScript file (e.g., &lt;code&gt;new Worker('worker.js')&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Communication happens via messages.&lt;/strong&gt; Your main script sends data to the worker using &lt;code&gt;postMessage()&lt;/code&gt;. The worker receives it through a &lt;code&gt;message&lt;/code&gt; event, processes the data, and &lt;code&gt;postMessage&lt;/code&gt;s the result back.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The worker has no access to the DOM&lt;/strong&gt; (no &lt;code&gt;document&lt;/code&gt;, no &lt;code&gt;window&lt;/code&gt;). It’s purely for computation. It can use &lt;code&gt;setTimeout&lt;/code&gt;, &lt;code&gt;fetch&lt;/code&gt;, &lt;code&gt;XMLHttpRequest&lt;/code&gt;, and the &lt;code&gt;File API&lt;/code&gt;, but it can’t touch your page or UI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple workers&lt;/strong&gt; can run in parallel, but keep in mind each worker gets its own JavaScript engine instance, so it’s not free in terms of memory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key insight: &lt;strong&gt;Web Workers are about parallelism, not concurrency.&lt;/strong&gt; They let you offload CPU-heavy work (like image processing, data sorting, or encryption) so your app stays responsive.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;When to use Web Workers:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Heavy computation that takes more than ~50ms (e.g., parsing a large CSV, calculating a hash, or generating a complex visualization).&lt;/li&gt;
&lt;li&gt;Real-time data processing in the background (e.g., a chat app that compresses/decompresses messages).&lt;/li&gt;
&lt;li&gt;Running long polling or WebSocket data handling without blocking UI.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;For quick operations (a few milliseconds). The overhead of creating a worker and serializing data to send it outweighs any benefit.&lt;/li&gt;
&lt;li&gt;For tasks that need DOM access. Workers can’t touch the DOM—you’d have to send results back and update the UI manually.&lt;/li&gt;
&lt;li&gt;For trivial parallel tasks when your app already runs fine. Premature parallelism adds complexity without payoff.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why should you care?&lt;/strong&gt; A sluggish app frustrates users and hurts engagement. Web Workers let you deliver smooth, professional experiences even during heavy workloads. If you’ve ever been told “the page freezes when I click Calculate,” Workers are your solution.&lt;/p&gt;

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

&lt;p&gt;Here’s a minimal before/after comparison:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before (blocking main thread):&lt;/strong&gt;&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;// main.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computeHeavyStuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bigData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// freezes UI until done&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;output&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&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 Web Worker):&lt;/strong&gt;&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;// main.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;worker&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;Worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;worker.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bigData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onmessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;output&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&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="c1"&gt;// UI stays smooth&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// worker.js&lt;/span&gt;
&lt;span class="nx"&gt;onmessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computeHeavyStuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example shows the pattern: you send data, the worker processes it in the background, and only when it’s done do you update the UI. Meanwhile, scrolling, clicking, and animations remain buttery smooth.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Use Web Workers when you need to keep your UI responsive during CPU-heavy tasks.&lt;/strong&gt; They’re not for every situation, but they’re an essential tool for any app that processes large amounts of data in the browser. For a deeper dive, check out the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API" rel="noopener noreferrer"&gt;MDN documentation on Web Workers&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webworkers</category>
      <category>javascriptparallelism</category>
      <category>backgroundthreads</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>HTTP/2 vs HTTP/3 : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Thu, 14 May 2026 14:01:14 +0000</pubDate>
      <link>https://dev.to/hongster85/http2-vs-http3-understand-in-3-minutes-3pl7</link>
      <guid>https://dev.to/hongster85/http2-vs-http3-understand-in-3-minutes-3pl7</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;HTTP/2 vs HTTP/3&lt;/strong&gt; is the debate between two major versions of the web’s foundational protocol—the rules that govern how your browser and a server exchange data. You encounter this problem because your web app feels slow on mobile networks, video streams buffer unpredictably, or your team is debating whether to upgrade infrastructure. If you’ve ever debugged a “slow API call” only to find the network itself is the bottleneck, you’ve lived this.&lt;/p&gt;

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

&lt;p&gt;Both HTTP/2 and HTTP/3 aim to make web requests faster, but they solve the problem in fundamentally different ways.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HTTP/2&lt;/strong&gt; introduced &lt;strong&gt;multiplexing&lt;/strong&gt;: it can send multiple requests and responses over a single &lt;strong&gt;TCP connection&lt;/strong&gt;. That’s a huge improvement over HTTP/1.1, which forced browsers to open dozens of parallel connections. But HTTP/2 still runs on &lt;strong&gt;TCP&lt;/strong&gt;, which has a fatal flaw: &lt;strong&gt;head-of-line blocking&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Imagine a single-lane highway carrying multiple delivery trucks. If one truck (a lost TCP packet) crashes, every truck behind it must stop and wait for the crash to be cleared. Even though HTTP/2 multiplexes requests, TCP forces them to share that single lane. One dropped packet delays &lt;em&gt;all&lt;/em&gt; simultaneous streams.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HTTP/3&lt;/strong&gt; replaces TCP with &lt;strong&gt;QUIC&lt;/strong&gt; (Quick UDP Internet Connections), which runs over &lt;strong&gt;UDP&lt;/strong&gt;. QUIC treats each request as an independent lane on the highway. If one lane has an accident, only that truck slows down—the rest keep flowing.&lt;/p&gt;

&lt;p&gt;Here’s the practical difference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HTTP/2&lt;/strong&gt; multiplexes over TCP → one lost packet blocks everything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTTP/3&lt;/strong&gt; multiplexes over QUIC/UDP → lost packets affect only their specific stream.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;QUIC also brings two other game-changers out of the box:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;0-RTT handshake&lt;/strong&gt; – For repeat connections, data starts flowing immediately (vs. TCP’s multi-round-trip setup).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connection migration&lt;/strong&gt; – Switching from Wi-Fi to mobile data doesn’t kill the connection. Your video call doesn’t drop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of it this way: HTTP/2 is a fast single-lane road, HTTP/3 is a multi-lane highway where each request gets its own lane.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;When to use HTTP/3:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your app is mobile-first (users on unreliable 4G/5G networks).&lt;/li&gt;
&lt;li&gt;You serve real-time features (live chat, collaborative editing, gaming).&lt;/li&gt;
&lt;li&gt;You stream video or large assets where packet loss is common.&lt;/li&gt;
&lt;li&gt;You care about first-byte latency (e.g., improving Time to First Byte).&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Your infrastructure (load balancers, CDNs, firewalls) doesn’t support QUIC yet.&lt;/li&gt;
&lt;li&gt;You work in a tightly controlled corporate network that blocks UDP traffic.&lt;/li&gt;
&lt;li&gt;You’re building for legacy clients that don’t support HTTP/3 (very old browsers or embedded devices).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why should you care?&lt;/strong&gt; If your users face high latency or spotty connections, HTTP/3 can dramatically improve perceived performance without any code changes on your side—it’s a transport-layer upgrade. In practice, most major CDNs and browsers already support it, so enabling it is often a configuration change.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Real-world scenario:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You’re loading a page with 100 small assets (images, CSS, scripts) over a mobile network with 2% packet loss.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HTTP/2&lt;/strong&gt;: The TCP connection sees a lost packet. All 100 assets wait while TCP retransmits that single packet. That’s a delay of ~50-100ms &lt;em&gt;per loss event&lt;/em&gt;. Your page load time jumps from 500ms to 1.5s.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTTP/3&lt;/strong&gt;: Only the stream affected by the lost packet pauses. The other 99 assets continue loading. Your page load time might only increase by 50ms.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The example demonstrates that &lt;strong&gt;HTTP/3’s independent streams make it dramatically more resilient on lossy networks&lt;/strong&gt;—which is exactly how most mobile users experience the internet.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;HTTP/3 over QUIC effectively eliminates the head-of-line blocking problem that still plagues HTTP/2 on unreliable networks.&lt;/strong&gt; If your users are on mobile or poor connections, enabling HTTP/3 is one of the highest-leverage performance improvements you can make—and it requires zero application code changes.&lt;/p&gt;

&lt;p&gt;For deeper investigation, read the &lt;a href="https://datatracker.ietf.org/doc/html/rfc9114" rel="noopener noreferrer"&gt;HTTP/3 specification (RFC 9114)&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>http3</category>
      <category>quic</category>
      <category>headoflineblocking</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>TLS/SSL Handshake : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Tue, 12 May 2026 14:00:45 +0000</pubDate>
      <link>https://dev.to/hongster85/tlsssl-handshake-understand-in-3-minutes-2fee</link>
      <guid>https://dev.to/hongster85/tlsssl-handshake-understand-in-3-minutes-2fee</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;TLS/SSL Handshake&lt;/strong&gt; is the cryptographic negotiation that happens between a client (like your browser) and a server before any encrypted data is exchanged—and every time you call an HTTPS API, deploy a web app, or debug a certificate error, you’re watching it happen (or fail).&lt;/p&gt;

&lt;p&gt;Imagine typing “&lt;a href="https://api.example.com%E2%80%9D" rel="noopener noreferrer"&gt;https://api.example.com”&lt;/a&gt; in your browser. In the ~100 milliseconds before the page loads, the client and server have already agreed on encryption algorithms, exchanged digital certificates, and generated session keys—without you lifting a finger. As a developer, you encounter this handshake whenever you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configure HTTPS for a web server (e.g., Nginx, Apache)&lt;/li&gt;
&lt;li&gt;Set up mTLS for microservice-to-microservice communication&lt;/li&gt;
&lt;li&gt;Debug SSL/TLS errors like &lt;code&gt;ERR_CERT_AUTHORITY_INVALID&lt;/code&gt; or &lt;code&gt;SSL_HANDSHAKE_FAILURE&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Tune performance because a slow handshake costs users time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’ve ever wondered “what’s really going on in that initial connection?”, or needed to explain it in a stand-up, this is your 3-minute answer.&lt;/p&gt;

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

&lt;p&gt;The TLS/SSL handshake is a &lt;strong&gt;three-phase dance&lt;/strong&gt; that takes place over the TCP connection. Think of it like two strangers meeting in a dark room, each proving their identity and agreeing on a secret code before talking.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hello &amp;amp; Cipher Suite Selection&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The client sends a &lt;code&gt;ClientHello&lt;/code&gt; message listing its supported TLS versions, cipher suites (e.g., &lt;code&gt;TLS_AES_128_GCM_SHA256&lt;/code&gt;), and a random number. The server responds with a &lt;code&gt;ServerHello&lt;/code&gt;, picking the strongest mutually supported version and cipher suite, plus its own random number. &lt;em&gt;They’ve now agreed on the rules of the conversation.&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Certificate Exchange &amp;amp; Authentication&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The server sends its &lt;strong&gt;digital certificate&lt;/strong&gt; (signed by a Certificate Authority) and, optionally, a request for the client’s certificate (for mTLS). The client verifies the certificate’s chain, checks expiration, and confirms the domain matches. This step proves the server is who it claims to be. &lt;em&gt;One side has shown ID.&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Key Exchange &amp;amp; Finalizing&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Using the two random numbers and the agreed-upon key exchange algorithm (e.g., &lt;strong&gt;Diffie-Hellman&lt;/strong&gt; or &lt;strong&gt;RSA&lt;/strong&gt;), both sides compute a shared &lt;strong&gt;session key&lt;/strong&gt;—without ever sending the key itself over the wire. They then send a &lt;code&gt;Finished&lt;/code&gt; message encrypted with that key. If both sides can decrypt it, the handshake is successful and encrypted data flows. &lt;em&gt;They now share a secret code.&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Why this matters to you:&lt;/strong&gt; The handshake adds &lt;strong&gt;one round trip&lt;/strong&gt; of latency (in modern TLS 1.3, it’s one round trip plus optional resumption). That’s why you see HTTP/2 and session resumption optimizations—they reuse previously established keys to skip the full dance on repeat visits.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  When to use it
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Any public-facing web service&lt;/strong&gt; that handles sensitive data (passwords, payment info, personal data). Today that’s &lt;strong&gt;every HTTPS site&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internal microservice communication&lt;/strong&gt; where you need mutual authentication (mTLS) to prevent rogue services from impersonating legitimate ones.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API integrations&lt;/strong&gt; with third-party services (e.g., Stripe, GitHub) that require TLS—you’re already using it whether you realize it or not.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  When NOT to use it
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Development-only environments&lt;/strong&gt; on localhost (e.g., &lt;code&gt;http://localhost:3000&lt;/code&gt;) where a self-signed certificate adds friction with no real security benefit. Tools like &lt;code&gt;mkcert&lt;/code&gt; can help if needed, but don’t force TLS in dev unless testing handshake behavior.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High-performance internal networks&lt;/strong&gt; with extremely low-latency requirements and trusted physical isolation. Even then, consider &lt;strong&gt;TLS 1.3&lt;/strong&gt;’s 0-RTT mode to minimize overhead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Legacy systems&lt;/strong&gt; that cannot be updated to support modern TLS 1.2/1.3—but be aware that continuing to use TLS 1.0/1.1 exposes you to known vulnerabilities (e.g., POODLE, BEAST).&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The handshake is &lt;strong&gt;the single most expensive operation&lt;/strong&gt; in an HTTPS connection. Misconfigured cipher suites, expired certificates, or too many round trips can add hundreds of milliseconds to page loads. As a developer, understanding the handshake helps you &lt;strong&gt;diagnose connectivity issues&lt;/strong&gt; (&lt;code&gt;openssl s_client -connect example.com:443&lt;/code&gt;) and &lt;strong&gt;tune performance&lt;/strong&gt; (e.g., enabling session resumption).&lt;/p&gt;

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

&lt;p&gt;Here’s a real-world scenario: your web app’s API calls suddenly fail with &lt;code&gt;SSL_ERROR_BAD_CERT_DOMAIN&lt;/code&gt;. Using &lt;code&gt;curl&lt;/code&gt; with verbose output reveals the handshake:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; https://api.example.com/v1/users
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the output, you’d see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*  SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
*  Server certificate:
*    subject: CN=*.example.com
*    start date: Feb 20 00:00:00 2024 GMT
*    expire date: Feb 20 23:59:59 2025 GMT
*    issuer: C=US, O=Let's Encrypt, CN=R3
*  SSL certificate verify ok.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The handshake succeeded: client and server agreed on TLS 1.3, the certificate is valid for &lt;code&gt;*.example.com&lt;/code&gt;, and the key exchange is complete. If instead you see &lt;code&gt;curl: (60) SSL certificate problem: unable to get local issuer certificate&lt;/code&gt;, the handshake failed at the certificate validation step—likely a self-signed or untrusted certificate. This is exactly what you’d debug by examining the handshake flow.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;The TLS/SSL handshake is a one-time cryptographic negotiation that establishes trust and shared encryption keys—and understanding its three phases (hello, certificate, key exchange) is the single most effective way to debug HTTPS failures and optimize connection latency.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For deeper exploration, read the &lt;a href="https://datatracker.ietf.org/doc/html/rfc8446" rel="noopener noreferrer"&gt;TLS 1.3 RFC 8446&lt;/a&gt; or watch a WireShark capture of a live handshake. But for now, you know enough to hold a conversation about it.&lt;/p&gt;

</description>
      <category>tlshandshake</category>
      <category>certificateverification</category>
      <category>keyexchange</category>
      <category>abotwrotethis</category>
    </item>
  </channel>
</rss>
