<?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>Forem: Hongster</title>
    <description>The latest articles on Forem by Hongster (@hongster85).</description>
    <link>https://forem.com/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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1600971%2Fe50d3487-f18f-404f-85ed-c5618bbd2777.jpeg</url>
      <title>Forem: Hongster</title>
      <link>https://forem.com/hongster85</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/hongster85"/>
    <language>en</language>
    <item>
      <title>Content Delivery Networks (CDNs) : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Tue, 05 May 2026 14:00:31 +0000</pubDate>
      <link>https://forem.com/hongster85/content-delivery-networks-cdns-understand-in-3-minutes-2c6c</link>
      <guid>https://forem.com/hongster85/content-delivery-networks-cdns-understand-in-3-minutes-2c6c</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;Content Delivery Network (CDN)&lt;/strong&gt; is a globally distributed network of servers that caches and serves your static content from locations closest to your users. You encounter the need for a CDN the moment your app loads slowly for users on the other side of the world, your origin server starts struggling under traffic spikes, or you hit bandwidth limits just from serving images and scripts. It’s that frustrating feeling when a user in Tokyo blames you for a 5-second page load—while your server sits comfortably in Virginia.&lt;/p&gt;

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

&lt;p&gt;A CDN works by storing copies of your static files (images, CSS, JavaScript, fonts, videos) on hundreds of servers spread across the globe. These servers are called &lt;strong&gt;Points of Presence (PoPs)&lt;/strong&gt; . When a user requests your site, the CDN routes the request to the nearest PoP (geographically) instead of your single origin server. If that PoP already has the file cached, it serves it instantly. If not, it fetches a fresh copy from your origin, caches it for future requests, and delivers it.&lt;/p&gt;

&lt;p&gt;Here are the key pieces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Edge servers&lt;/strong&gt; – The actual servers in PoPs that store and serve cached content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS routing&lt;/strong&gt; – The CDN’s DNS system automatically resolves the user’s request to the closest edge server based on their IP location.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caching rules&lt;/strong&gt; – You control what gets cached and for how long using HTTP headers (like &lt;code&gt;Cache-Control&lt;/code&gt; and &lt;code&gt;Expires&lt;/code&gt;). Your origin server stays the authoritative source; the CDN is just a smart middle layer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Analogy:&lt;/strong&gt; Think of a CDN like a chain of local bookstores. You write one book (your content) and keep the master copy at your publisher’s warehouse (origin server). Instead of every reader traveling to the warehouse, you ship copies to local bookstores around the world. Readers walk to the nearest bookstore—fast, no traffic jams.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Use a CDN when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your user base is global (even a single other continent justifies it).&lt;/li&gt;
&lt;li&gt;You serve a lot of static assets (images, videos, libraries, fonts).&lt;/li&gt;
&lt;li&gt;You expect traffic spikes (product launches, viral content, Black Friday).&lt;/li&gt;
&lt;li&gt;You want to reduce load on your origin server and save on bandwidth costs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Don’t use a CDN when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your content is entirely dynamic and personalized per user (e.g., a dashboard that changes every request with no common cacheable elements). CDNs can still accelerate dynamic content via edge compute or API caching, but that’s a more advanced setup.&lt;/li&gt;
&lt;li&gt;Your audience is extremely small and all in one region—standard hosting with a good cache layer might be enough.&lt;/li&gt;
&lt;li&gt;You need real-time, low-latency writes (CDNs are optimized for read-heavy, cache-friendly workloads).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Common use cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;E-commerce product images&lt;/strong&gt; – A CDN serves catalog thumbnails instantly, regardless of where the customer shops.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Video streaming platforms&lt;/strong&gt; – Edge servers buffer and deliver video chunks, reducing buffering and origin load.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API responses&lt;/strong&gt; – Cacheable API endpoints (e.g., public product listings) can be served from edge caches, slashing response times.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;&lt;strong&gt;Before CDN:&lt;/strong&gt; A user in Sydney fetches &lt;code&gt;https://your-app.com/styles.css&lt;/code&gt; from your single server in Virginia. RTT (round-trip time) is ~250ms, and the server may need to compress and send the file each time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After CDN:&lt;/strong&gt; You configure a CDN to cache &lt;code&gt;styles.css&lt;/code&gt;. The user’s request goes to a Sydney PoP. The PoP serves the file in &amp;lt;10ms.&lt;/p&gt;

&lt;p&gt;Here’s a simple HTML snippet showing how you reference a CDN-delivered file (using a popular CDN for a front-end library):&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="c"&gt;&amp;lt;!-- Without CDN (self-hosted) --&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;"/js/react.development.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- With CDN (served from nearest edge) --&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://cdn.jsdelivr.net/npm/react@18.2.0/umd/react.development.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;The second line automatically routes the user to the nearest edge server hosting that React file—no infrastructure changes on your side.&lt;/p&gt;

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

&lt;p&gt;Use a CDN to dramatically cut global latency and take the heat off your origin server—but only for content that can be cached. Cache aggressively, set proper TTLs, and treat the CDN as a reliable, scalable middle layer you don’t have to manage yourself.&lt;/p&gt;

&lt;p&gt;For deeper learning, check out &lt;a href="https://www.cloudflare.com/learning/cdn/what-is-a-cdn/" rel="noopener noreferrer"&gt;Cloudflare’s CDN overview&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>contentdeliverynetwork</category>
      <category>edgeservers</category>
      <category>cachingrules</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Hydration in React/Next.js : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Thu, 30 Apr 2026 14:00:29 +0000</pubDate>
      <link>https://forem.com/hongster85/hydration-in-reactnextjs-understand-in-3-minutes-3917</link>
      <guid>https://forem.com/hongster85/hydration-in-reactnextjs-understand-in-3-minutes-3917</guid>
      <description>&lt;h2&gt;
  
  
  Hydration in React/Next.js
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Problem Statement
&lt;/h3&gt;

&lt;p&gt;Hydration is the process where a server-rendered HTML page becomes an interactive React application on the client. You hit this problem when your Next.js page loads instantly (thanks to server-side rendering) but then suddenly flickers, loses state, or feels janky as JavaScript kicks in. Sound familiar? You’ve likely seen the dreaded “hydration mismatch” warning in your console. It happens because the static HTML the server sent doesn’t perfectly match the React tree the browser tries to build. Why does this matter? Because without proper hydration, your app can break functionality like click handlers, form inputs, or third-party widgets that rely on client-side JavaScript.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Core Explanation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Hydration is the bridge between static HTML and dynamic React.&lt;/strong&gt; Here’s how it works in three steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server sends dry HTML&lt;/strong&gt;: Next.js renders your React components on the server, producing plain HTML with no JavaScript. This HTML is fast to display—users see content immediately.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Browser renders that HTML&lt;/strong&gt;: The browser paints the page. It looks complete, but nothing is interactive yet—no buttons work, no dropdowns open.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;React “waters” the HTML&lt;/strong&gt;: React’s JavaScript bundle downloads and runs. React attaches event listeners (like &lt;code&gt;onClick&lt;/code&gt;), initializes component state, and connects the virtual DOM to the existing DOM nodes. This is hydration—React takes the server’s static markup and brings it to life.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The catch? React expects the server-sent HTML structure to exactly match what it would render on the client. If there’s any difference—say, a &lt;code&gt;useEffect&lt;/code&gt; that changes something on mount, or a component that uses &lt;code&gt;window.innerWidth&lt;/code&gt;—React throws a mismatch error and re-renders the whole tree. That’s where performance issues and user-facing glitches start.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Simple analogy&lt;/strong&gt;: Think of a pre-filled form on paper. Server sends you a printed form with all fields filled. Hydration is you taking that paper form, scanning it, and turning it into an editable digital document where you can click buttons and type. If the digital version has a different layout (extra field, missing label), the scan fails.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Practical Context
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Use hydration when you need fast initial page loads and SEO&lt;/strong&gt;, which is almost every server-rendered Next.js app. Hydration is automatic in Next.js for pages using &lt;code&gt;getServerSideProps&lt;/code&gt; or &lt;code&gt;getStaticProps&lt;/code&gt;. You don’t opt in—you opt out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Avoid hydration when your page has no dynamic content at all.&lt;/strong&gt; If every visitor sees exactly the same static marketing page, skip React entirely and use a plain HTML/CSS approach. Also, avoid heavy hydration for pages that rely heavily on client-only data (like dashboards) – consider using &lt;code&gt;next/dynamic&lt;/code&gt; with &lt;code&gt;ssr: false&lt;/code&gt; to skip server rendering entirely for those components.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;E-commerce product pages&lt;/strong&gt;: SEO needs server-rendered content, but “Add to Cart” buttons and image galleries need hydration. Mismatches here cause cart logic to break silently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blog with comments&lt;/strong&gt;: Server renders the article; hydration enables live comment submission without a page reload. Mismatch often happens if the server shows a logout button but the client knows the user is logged in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Admin dashboards&lt;/strong&gt;: You may prefer client-only rendering for authenticated pages to avoid hydration mismatch with user-specific data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why should you care?&lt;/strong&gt; Hydration mismatches cause bugs that are hard to reproduce—they happen only on first load, then disappear on subsequent navigations. They degrade Core Web Vitals (Layout Shifts from re-renders) and user trust.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Quick Example
&lt;/h3&gt;

&lt;p&gt;Here’s a common hydration mismatch and how to fix it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Problem: uses client-only data during server render&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Greeting&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&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="c1"&gt;// This runs only on client – server sends empty name&lt;/span&gt;
    &lt;span class="nf"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;username&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="p"&gt;[])&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello, &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ Fix: ensure server output matches client initial render&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Greeting&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&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="c1"&gt;// Same logic, but initial state is 'User' – both sides match&lt;/span&gt;
    &lt;span class="nf"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;username&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User&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="p"&gt;[])&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello, &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;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;: The server renders &lt;code&gt;&amp;lt;h1&amp;gt;Hello, &amp;lt;/h1&amp;gt;&lt;/code&gt; (empty name). The client tries to build the same, but &lt;code&gt;useEffect&lt;/code&gt; runs and sets &lt;code&gt;name&lt;/code&gt; to a stored value. React detects a difference (&lt;code&gt;''&lt;/code&gt; vs &lt;code&gt;'Alice'&lt;/code&gt;) and throws a hydration mismatch. By initializing &lt;code&gt;useState&lt;/code&gt; with a fallback value that matches server output, you prevent the mismatch. The &lt;code&gt;useEffect&lt;/code&gt; will still update the UI after hydration—but without re-rendering the whole page.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Key Takeaway
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Always make your server-rendered output identical to your component’s initial client render&lt;/strong&gt;—ensure &lt;code&gt;useState&lt;/code&gt; default values and any conditions based on &lt;code&gt;typeof window&lt;/code&gt; are consistent. For deeper dives, read &lt;a href="https://react.dev/reference/react-dom/hydrate" rel="noopener noreferrer"&gt;React’s official hydration documentation&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>reacthydration</category>
      <category>nextjs</category>
      <category>hydrationmismatch</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Progressive Web Apps (PWAs) : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Tue, 28 Apr 2026 14:00:27 +0000</pubDate>
      <link>https://forem.com/hongster85/progressive-web-apps-pwas-understand-in-3-minutes-3ohc</link>
      <guid>https://forem.com/hongster85/progressive-web-apps-pwas-understand-in-3-minutes-3ohc</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;Progressive Web App (PWA)&lt;/strong&gt; is a website that behaves like a native mobile app — it loads instantly, works offline, and can send push notifications — without requiring users to visit an app store. You’ve probably shipped a web app only to hear “it feels sluggish” or “why can’t I use it without internet?” Meanwhile, your product lead wants the engagement of a native app but can’t justify two separate codebases. PWAs bridge that gap, giving you app-like experiences from a single web codebase, but only if you know when and how to use them.&lt;/p&gt;

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

&lt;p&gt;A PWA is a website enhanced with three core technologies that together unlock native-like capabilities. Think of it like a Swiss Army knife: your regular website is the blade (content and logic), and the PWA features are the extra tools (offline, push, home screen) that fold out when needed.&lt;/p&gt;

&lt;p&gt;Here’s what makes a PWA work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Service Worker&lt;/strong&gt; – A JavaScript file that runs in the background, separate from your web page. It intercepts network requests and acts as a smart cache. When the user has connectivity, it updates cached resources. When offline, it serves the last-known-good version of your app. This is the engine behind offline support and fast loading.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Web App Manifest&lt;/strong&gt; – A JSON file that tells the browser how your app should look when installed on the home screen. It defines the icon, splash screen, theme color, and display mode (e.g., full-screen). Without this, the user can’t “install” your PWA.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTTPS&lt;/strong&gt; – Service workers only run on secure origins (HTTPS). This ensures that the code intercepting network traffic hasn’t been tampered with. Non-negotiable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The magic happens when a user first visits your site. The browser silently installs the service worker. On subsequent visits, the service worker serves cached assets, making load times near-instant (even on flaky networks). If the user taps “Add to Home Screen,” the manifest kicks in, and your app appears in their app drawer — no store required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analogy&lt;/strong&gt;: A PWA is like a library book you photocopy. The original (server) might be far away, but you keep a copy in your backpack (cache). You can read it anywhere, even in a tunnel. When you get back to WiFi, you update your copy with new pages (background sync).&lt;/p&gt;

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

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

&lt;ul&gt;
&lt;li&gt;You need offline or poor-network capability (e.g., a news reader, a field-service checklist, a travel guide).&lt;/li&gt;
&lt;li&gt;You want to reduce friction to re-engage users (push notifications + home screen install = higher retention).&lt;/li&gt;
&lt;li&gt;You’re building a content-driven or lightweight app and want to skip the app store approval process.&lt;/li&gt;
&lt;li&gt;You have a web app already and want to improve performance — adding a service worker can be incremental.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Don’t use PWAs when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your app requires deep device hardware access (Bluetooth, NFC, camera in background) — PWAs still can’t do everything native apps can (though APIs are expanding).&lt;/li&gt;
&lt;li&gt;You need sophisticated background processing (e.g., a fitness tracker recording GPS continuously) — service workers have limited background execution time.&lt;/li&gt;
&lt;li&gt;Your audience heavily relies on iOS — Safari’s PWA support has historically lagged (push notifications only arrived in iOS 16.4, and some features still differ). For enterprise/B2B apps on Android, PWAs are a no-brainer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Common use cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;E-commerce&lt;/strong&gt; – Pinterest’s PWA saw a 60% increase in core engagement and 44% increase in user-generated ad revenue.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;News/Media&lt;/strong&gt; – The Washington Post’s PWA reduced load time from 4 seconds to &amp;lt;1 second.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Travel/Offline-first&lt;/strong&gt; – Trivago’s PWA achieved a 150% increase in user engagement by providing offline hotel search.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Why you should care&lt;/strong&gt;: PWAs can boost conversion rates, reduce bounce rates (because pages load fast), and shrink your development and maintenance costs. If your metric is “user action” (click, purchase, read), a PWA often outperforms both a slow website and a minimal native app.&lt;/p&gt;

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

&lt;p&gt;Here’s the minimal code to register a service worker — the first step to making any site a PWA:&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;// In your main script (e.g., app.js)&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;serviceWorker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;serviceWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/sw.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reg&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;SW registered&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reg&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="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;SW failed&lt;/span&gt;&lt;span class="dl"&gt;'&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the corresponding &lt;code&gt;sw.js&lt;/code&gt; (service worker) for offline fallback:&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="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;respondWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;catch&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;return&lt;/span&gt; &lt;span class="nx"&gt;caches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/offline.html&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="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 it demonstrates&lt;/strong&gt;: The first script checks if the browser supports service workers (modern browsers do), then registers the file &lt;code&gt;sw.js&lt;/code&gt;. The &lt;code&gt;sw.js&lt;/code&gt; intercepts every network request. If the fetch fails (user is offline), it serves a cached &lt;code&gt;offline.html&lt;/code&gt; page instead of showing a browser error. That’s the core of offline resilience — about 10 lines of code.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;A PWA is not a framework or a rewrite; it’s a progressive enhancement you add to your existing website using a service worker and a manifest.&lt;/strong&gt; You can ship offline support and “installability” incrementally, starting with just a few lines of JavaScript. If you want to dive deeper, read the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers" rel="noopener noreferrer"&gt;MDN guide on service workers&lt;/a&gt; — it covers caching strategies and lifecycle.&lt;/p&gt;

</description>
      <category>progressivewebapp</category>
      <category>serviceworker</category>
      <category>offlinesupport</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Service Workers : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Thu, 23 Apr 2026 14:00:28 +0000</pubDate>
      <link>https://forem.com/hongster85/service-workers-understand-in-3-minutes-2m7m</link>
      <guid>https://forem.com/hongster85/service-workers-understand-in-3-minutes-2m7m</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;Service Worker&lt;/strong&gt; is a script that runs in the background of your web browser, separate from your web page, acting as a programmable network proxy. You hit this problem when you need your web app to work offline, load instantly even on slow networks, or send push notifications—things traditional web pages simply can't do. Every developer has faced that moment when a user tabs away, loses signal, and the app becomes a blank white page. Service Workers are the solution to that broken experience.&lt;/p&gt;

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

&lt;p&gt;Think of a Service Worker as a &lt;strong&gt;network traffic manager&lt;/strong&gt; that sits between your web app and the internet. Unlike regular JavaScript that dies when you close the tab, a Service Worker lives on in the browser, listening for events and intercepting network requests even when your page isn't open.&lt;/p&gt;

&lt;p&gt;Here's how it works in three key steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Registration &amp;amp; Installation&lt;/strong&gt;: Your web app tells the browser to register a Service Worker script. The browser installs it in the background, giving you a chance to pre-cache critical assets (HTML, CSS, JS, images) so they're ready for offline use.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Activation &amp;amp; Interception&lt;/strong&gt;: Once installed, the Service Worker activates and begins intercepting every network request your app makes. It can respond from its cache, forward to the network, or do a hybrid of both.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lifecycle Control&lt;/strong&gt;: The Service Worker runs on its own thread, completely independent from your UI. It can handle push events, sync data in the background, and even update itself silently when you deploy a new version.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Analogy&lt;/strong&gt;: Imagine a smart butler who memorizes your favorite meals. When you ask for one, they check the kitchen (cache) first. If it's there, you get it instantly. If not, they order from the restaurant (network). And if the restaurant is closed (offline), they still serve you from what's already in the kitchen. That's a Service Worker.&lt;/p&gt;

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

&lt;p&gt;Use Service Workers when you need &lt;strong&gt;reliable performance&lt;/strong&gt; under poor network conditions, &lt;strong&gt;offline functionality&lt;/strong&gt;, or &lt;strong&gt;background capabilities&lt;/strong&gt; like push notifications. They're essential for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Progressive Web Apps (PWAs)&lt;/strong&gt; offering offline-first experiences (like a notes app or news reader)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Media-heavy sites&lt;/strong&gt; where users expect instant loading from cache (like an image gallery)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time data apps&lt;/strong&gt; that need background sync (like an email client posting drafts when connectivity returns)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Don't use&lt;/strong&gt; Service Workers for simple static brochure sites where the network is always reliable, or for apps that need to access the DOM (they can't). Also avoid if your user base uses older browsers without HTTPS support (Service Workers require HTTPS or localhost).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why care?&lt;/strong&gt; A Service Worker transforms your web app from "works when online" to "works when human." Users with flaky connections won't abandon your app. And you get push notification superpowers without needing a native app store.&lt;/p&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Registration - typically in your main page script&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;serviceWorker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;serviceWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/sw.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// sw.js - A simple cache-first strategy&lt;/span&gt;
&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;respondWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;caches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// Try cache first&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// Fallback to network&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Offline&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;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="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 shows the minimal pattern: the &lt;code&gt;fetch&lt;/code&gt; event listener intercepts every request, checks the cache, and only goes to the network as a fallback. Users get instant loading from cache, and the app works offline for anything already visited.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Service Workers let you turn your web app into a reliable, offline-capable experience&lt;/strong&gt; without building a native mobile app. Start by adding one to a single route with a cache-first strategy—you'll see instant performance wins. For deeper dives, check out the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API" rel="noopener noreferrer"&gt;MDN Service Worker documentation&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>serviceworker</category>
      <category>offlinefirst</category>
      <category>progressivewebapp</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Logging Best Practices : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Tue, 21 Apr 2026 14:00:57 +0000</pubDate>
      <link>https://forem.com/hongster85/logging-best-practices-understand-in-3-minutes-39f7</link>
      <guid>https://forem.com/hongster85/logging-best-practices-understand-in-3-minutes-39f7</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Problem Statement&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Logging best practices are a set of guiding principles for creating log output that is genuinely useful for troubleshooting and monitoring, rather than just generating noise. You encounter this problem every time you’re staring at a massive, chaotic log file trying to find why a customer’s request failed, or when an "error" alert wakes you up at 2 AM, only to discover it was a minor, expected issue. It’s the pain of having data but no insight, because your logs tell you &lt;em&gt;something&lt;/em&gt; happened, but not &lt;em&gt;why&lt;/em&gt; or &lt;em&gt;in what context&lt;/em&gt;.&lt;/p&gt;

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

&lt;p&gt;Think of good logging like a well-organized detective’s notebook. A bad log is a single, scrawled line: "Saw suspect." A good log provides the structured, essential facts: "Who, What, When, Where, and Why." Implementing logging best practices means intentionally crafting those log entries to be immediately actionable.&lt;/p&gt;

&lt;p&gt;Here’s how it works by focusing on a few key components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Structure Your Data:&lt;/strong&gt; Instead of writing long, free-text sentences, log in a structured format like JSON. This turns a log line from &lt;code&gt;"User login failed for john@doe.com"&lt;/code&gt; into machine-readable key-value pairs: &lt;code&gt;{"event": "login_failed", "user": "john@doe.com", "reason": "invalid_password", "ip": "192.168.1.1"}&lt;/code&gt;. This allows you to search, filter, and aggregate logs effortlessly in tools like Elasticsearch or Datadog.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Use Meaningful Log Levels:&lt;/strong&gt; Not everything is an &lt;strong&gt;ERROR&lt;/strong&gt;. Use levels deliberately:

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;ERROR:&lt;/strong&gt; A serious failure in the application that needs immediate attention (e.g., a database connection is lost).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;WARN:&lt;/strong&gt; An unexpected event that doesn’t break functionality but might indicate a future problem (e.g., a deprecated API was called).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;INFO:&lt;/strong&gt; High-level events that track normal application flow (e.g., "Order 1234 completed").&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;DEBUG:&lt;/strong&gt; Detailed information valuable only during active development or troubleshooting.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Add Context, Not Just Messages:&lt;/strong&gt; Every log entry should include a unique correlation ID (like a request ID) that ties together all logs for a single user transaction across different services. Always include relevant identifiers (user ID, transaction ID, file name) so you can trace the full story of an event.&lt;/li&gt;

&lt;/ul&gt;

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

&lt;p&gt;You should adopt these practices for any application that runs in a non-local environment, especially production. They are &lt;strong&gt;critical for distributed systems&lt;/strong&gt; (microservices, serverless), where tracing a request across services is impossible without structured, correlated logs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When are simpler logs okay?&lt;/strong&gt; For a tiny, personal script you run once, or during the earliest prototyping phase, you can skip the ceremony. The overhead might outweigh the benefit.&lt;/p&gt;

&lt;p&gt;You should care about this because good logs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Slash Debugging Time:&lt;/strong&gt; Find the root cause of production issues in minutes, not hours.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Enable Effective Monitoring:&lt;/strong&gt; Power your alerting dashboards so you're alerted on real problems, not noise.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Provide Business Insights:&lt;/strong&gt; Logged events (e.g., &lt;code&gt;"purchase_completed"&lt;/code&gt;) can be analyzed to understand user behavior.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you spend more than a few minutes searching for a problem in your logs, it's time to invest in these practices.&lt;/p&gt;

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

&lt;p&gt;Here’s a before-and-after comparison of logging an error in an API endpoint:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before (Unstructured, No Context):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Failed to process order&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;em&gt;This tells you a failure occurred, but nothing more. Which order? Why? For whom?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After (Structured &amp;amp; Contextual):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Order processing failure&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;extra&lt;/span&gt;&lt;span class="o"&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;event&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;order_processing_failed&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;order_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user_id&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="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;payment_gateway_tx_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;transaction_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;correlation_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;correlation_id&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;This single entry provides all the forensic data needed to diagnose the issue, find the user, and trace the request across the system.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Your logs are a primary diagnostic tool; treat them with the same care as your code by making them &lt;strong&gt;structured, contextual, and appropriately leveled&lt;/strong&gt; so you can solve problems faster. For a definitive guide, review the &lt;strong&gt;Twelve-Factor App&lt;/strong&gt; methodology’s section on &lt;a href="https://12factor.net/logs" rel="noopener noreferrer"&gt;logs&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>loggingbestpractices</category>
      <category>structuredlogging</category>
      <category>loglevels</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Configuration Management : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Thu, 16 Apr 2026 14:00:59 +0000</pubDate>
      <link>https://forem.com/hongster85/configuration-management-understand-in-3-minutes-1n1j</link>
      <guid>https://forem.com/hongster85/configuration-management-understand-in-3-minutes-1n1j</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Problem Statement&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Configuration management&lt;/strong&gt; is the systematic practice of handling the settings, options, and environment variables that your software needs to run, without baking them directly into your code. You encounter this problem every time you need to run the same application in different places—like when your code works perfectly on your laptop with &lt;code&gt;localhost&lt;/code&gt; but crashes in production because the database password is hardcoded, or when a teammate can't run the project because they use a different API key. It’s the mess of manually changing files for each environment, which is tedious and a breeding ground for errors.&lt;/p&gt;

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

&lt;p&gt;At its heart, configuration management separates the &lt;strong&gt;"what"&lt;/strong&gt; your app does from the &lt;strong&gt;"where"&lt;/strong&gt; and &lt;strong&gt;"how"&lt;/strong&gt; it runs. Instead of writing &lt;code&gt;database = "localhost"&lt;/code&gt; in your source files, you externalize those values. The system then loads the correct values based on the current context (e.g., development, testing, production).&lt;/p&gt;

&lt;p&gt;Think of it like a recipe. The source code is the list of instructions (sauté, bake, mix). The configuration is the list of ingredients and quantities. You wouldn't rewrite the entire recipe to double it; you just refer to a different ingredient list. Configuration management provides that separate, swappable list.&lt;/p&gt;

&lt;p&gt;It typically involves three key parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Configuration Sources:&lt;/strong&gt; The files, environment variables, or secret vaults where key-value pairs (like &lt;code&gt;DB_HOST&lt;/code&gt;, &lt;code&gt;API_URL&lt;/code&gt;) are stored.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;A Management Tool/Library:&lt;/strong&gt; The code or system that knows how to find, load, validate, and merge these values from different sources into a single, usable set for your application. Examples include simple &lt;code&gt;.env&lt;/code&gt; files with a library like &lt;code&gt;dotenv&lt;/code&gt;, or dedicated tools like &lt;strong&gt;Ansible&lt;/strong&gt;, &lt;strong&gt;Chef&lt;/strong&gt;, or cloud-native services.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Environment Isolation:&lt;/strong&gt; A clear rule that different environments (dev, staging, prod) get entirely different configuration data, even though the code remains identical.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;&lt;strong&gt;Use configuration management when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  You work on a team (everyone needs consistent setups).&lt;/li&gt;
&lt;li&gt;  Your app runs in multiple environments (like your laptop, a CI server, and a production cloud).&lt;/li&gt;
&lt;li&gt;  You use sensitive data (API keys, passwords) that shouldn't be in your source code repository.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;You might &lt;em&gt;not&lt;/em&gt; need a formal system for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  A tiny, one-person script that runs in only one place and has no secrets.&lt;/li&gt;
&lt;li&gt;  When the overhead of managing configuration files outweighs the benefit.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Database Connections:&lt;/strong&gt; Swapping connection strings between local, test, and production databases automatically.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Feature Flags:&lt;/strong&gt; Turning features on or off for specific users or environments without a code deployment.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Third-Party Service Config:&lt;/strong&gt; Pointing to different external API endpoints (e.g., a sandbox vs. a live payment gateway).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You should care because it makes your application more &lt;strong&gt;portable, secure, and less error-prone&lt;/strong&gt;. It’s a foundational practice for reliable deployments and team collaboration.&lt;/p&gt;

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

&lt;p&gt;Here’s a simple before-and-after look at connecting to a database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before (Hardcoded - The Problem):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app.py
&lt;/span&gt;&lt;span class="n"&gt;db_host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;db_password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;supersecret123&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# Oops, now in git history!
&lt;/span&gt;&lt;span class="nf"&gt;connect_to_database&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;db_password&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 Configuration Management - The Solution):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;

&lt;span class="nf"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# Loads values from a `.env` file
&lt;/span&gt;&lt;span class="n"&gt;db_host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DB_HOST&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;db_password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DB_PASSWORD&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Value is read from the environment
&lt;/span&gt;&lt;span class="nf"&gt;connect_to_database&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db_host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;db_password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="c"&gt;# .env file (NOT committed to git)
&lt;/span&gt;&lt;span class="n"&gt;DB_HOST&lt;/span&gt;=&lt;span class="n"&gt;localhost&lt;/span&gt;
&lt;span class="n"&gt;DB_PASSWORD&lt;/span&gt;=&lt;span class="n"&gt;supersecret123&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example demonstrates the core principle: &lt;strong&gt;separating secret and environment-specific values from the application source code.&lt;/strong&gt; The code is now environment-agnostic and secure.&lt;/p&gt;

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

&lt;p&gt;The single most important rule is this: &lt;strong&gt;Your application's configuration should always be separate from its code, allowing you to deploy the same build artifact anywhere.&lt;/strong&gt; If you want to explore a simple, universal starting point, learn about the &lt;a href="https://12factor.net/config" rel="noopener noreferrer"&gt;12-Factor App methodology for configuration&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>configurationmanagement</category>
      <category>environmentisolation</category>
      <category>twelvefactorapp</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Lazy Loading : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Tue, 14 Apr 2026 14:01:03 +0000</pubDate>
      <link>https://forem.com/hongster85/lazy-loading-understand-in-3-minutes-b81</link>
      <guid>https://forem.com/hongster85/lazy-loading-understand-in-3-minutes-b81</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Problem Statement&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Lazy loading is a design pattern that delays the loading of a resource until the moment it's actually needed.&lt;/strong&gt; You encounter the need for it because loading everything upfront—whether it's images on a webpage, data from a database, or modules in your app—slows things down unnecessarily. Think about an e-commerce site with hundreds of product images; it's wasteful to download them all when a user might only see the first five. Or a massive web application that forces users to wait for the entire codebase to load before they can click "Login." Lazy loading solves this by shifting work until it's truly required, making your applications feel snappier and more efficient from the very first interaction.&lt;/p&gt;

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

&lt;p&gt;At its heart, lazy loading works on a simple principle: don't do work until you have to. Instead of loading all resources during initial setup, you set up placeholders and load the real content on-demand when a specific &lt;strong&gt;trigger&lt;/strong&gt; occurs.&lt;/p&gt;

&lt;p&gt;Think of it like a restaurant with a huge menu. Instead of cooking every single dish in the morning (loading everything upfront), they prepare ingredients and start cooking a specific dish only when you order it (loading on demand). This saves time, energy, and resources.&lt;/p&gt;

&lt;p&gt;Here’s how the pattern typically breaks down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;The Placeholder:&lt;/strong&gt; Initially, you load a lightweight substitute. For an image, this is often a small, low-quality placeholder or an empty &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; with a fixed size. For code, it's a stub or a lightweight reference.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;The Trigger:&lt;/strong&gt; This is the event that signals the real resource is needed. Common triggers include: a user scrolling an image into the viewport, clicking a button to open a feature, or navigating to a specific route in a single-page application.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;The Loading Mechanism:&lt;/strong&gt; When the trigger fires, the system fetches and instantiates the real resource (the high-resolution image, the JavaScript module, the data chunk) and swaps it in for the placeholder. This is often handled by modern browser APIs like &lt;code&gt;IntersectionObserver&lt;/code&gt; for images or dynamic &lt;code&gt;import()&lt;/code&gt; for JavaScript.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key components are the lightweight initial state, the event listener waiting for a signal, and the subsequent load-and-swap operation.&lt;/p&gt;

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

&lt;p&gt;Use &lt;strong&gt;lazy loading&lt;/strong&gt; when you have large, non-critical resources that are not needed immediately for the page or application to function. It's perfect for:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Below-the-fold images and media&lt;/strong&gt; on content-heavy websites.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Components/modules/routes&lt;/strong&gt; in single-page applications (like React, Vue, or Angular apps) that aren't part of the initial login or home screen.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Data for secondary features&lt;/strong&gt;, such as comments on a blog post or details in an accordion panel.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Avoid lazy loading&lt;/strong&gt; for critical resources. Anything required for your &lt;strong&gt;Core Web Vitals&lt;/strong&gt;, especially the Largest Contentful Paint (LCP), should load immediately. Don't lazy load your main hero image, primary CSS, or the JavaScript needed for your initial render. You should also be cautious with content that will be needed almost instantly, as the slight loading delay can be jarring.&lt;/p&gt;

&lt;p&gt;You should care because this is one of the highest-impact patterns for improving perceived performance. It reduces initial load time, saves bandwidth for your users, and can significantly improve key performance metrics. If your app feels sluggish on first load or you're bundling massive amounts of code, lazy loading is likely your first tool to reach for.&lt;/p&gt;

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

&lt;p&gt;Consider a webpage with a long list of article previews, each with an image. The traditional approach loads all 50 images at once. With lazy loading, you only load images as the user scrolls near them.&lt;/p&gt;

&lt;p&gt;Here’s a simplified look at the HTML change, using the native &lt;code&gt;loading="lazy"&lt;/code&gt; attribute for images:&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="c"&gt;&amp;lt;!-- Old Way: Loads immediately, regardless of position on page --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"article-image-1.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Article 1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Lazy Loaded: Loads only when near the viewport --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"article-image-1.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Article 1"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This single attribute tells the browser to defer loading the image until it's within a calculated distance of the viewport. The example demonstrates how a minimal change can offload significant work, allowing the browser to prioritize the images the user actually needs to see right now.&lt;/p&gt;

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

&lt;p&gt;The actionable insight is this: &lt;strong&gt;Treat loading as a strategic decision, not an inevitable upfront cost.&lt;/strong&gt; Defer any work that isn't essential for the first interaction to create a faster, more responsive experience. For a deep dive into implementation techniques, the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Performance/Lazy_loading" rel="noopener noreferrer"&gt;MDN Web Docs on Lazy Loading&lt;/a&gt; is an excellent next stop.&lt;/p&gt;

</description>
      <category>lazyloading</category>
      <category>performanceoptimization</category>
      <category>webdev</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Virtual DOM vs Real DOM : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Thu, 09 Apr 2026 14:00:36 +0000</pubDate>
      <link>https://forem.com/hongster85/virtual-dom-vs-real-dom-understand-in-3-minutes-4m8</link>
      <guid>https://forem.com/hongster85/virtual-dom-vs-real-dom-understand-in-3-minutes-4m8</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Problem Statement&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Understanding the &lt;strong&gt;Virtual DOM vs. Real DOM&lt;/strong&gt; means knowing why modern frameworks like React manage your web page's structure with a lightweight JavaScript copy, instead of directly manipulating the browser's built-in model. You encounter this concept when your app's UI feels slow during frequent updates—like in a live dashboard, a interactive form, or a fast-scrolling list—and you need a predictable, high-performance way to make those changes.&lt;/p&gt;

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

&lt;p&gt;Think of the &lt;strong&gt;Real DOM&lt;/strong&gt; as the official, detailed blueprint of a building that the city hall maintains. Every time you want to move a wall (&lt;strong&gt;update the UI&lt;/strong&gt;), you must file paperwork to edit the official blueprint, a process that is slow and requires the whole document to be re-filed. In web terms, the Real DOM is the browser's live tree structure of your page; directly changing it is computationally expensive.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Virtual DOM&lt;/strong&gt; is your private, quick-to-edit sketch of that blueprint. Here’s how it works in three steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Virtual Copy:&lt;/strong&gt; Your framework (e.g., React) creates a lightweight JavaScript object that mirrors the Real DOM. This is the Virtual DOM.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Update the Sketch:&lt;/strong&gt; When your app's state changes, the framework creates a &lt;em&gt;new&lt;/em&gt; Virtual DOM object representing the desired UI.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Smart Comparison (Diffing):&lt;/strong&gt; The framework compares this new Virtual DOM snapshot with the previous one to pinpoint the &lt;strong&gt;exact&lt;/strong&gt; differences (e.g., one changed text label).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Efficient Update:&lt;/strong&gt; It then calculates the most efficient set of instructions and applies &lt;em&gt;only those necessary changes&lt;/em&gt; to the Real DOM.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The core principle is batching and minimizing direct, costly Real DOM operations. You describe your desired UI state, and the Virtual DOM system figures out the most efficient way to get there.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;When you should care:&lt;/strong&gt;&lt;br&gt;
You are likely using the Virtual DOM pattern if you are building a &lt;strong&gt;complex, interactive Single-Page Application (SPA)&lt;/strong&gt; with frameworks like React, Vue, or Preact. It’s invaluable when you have frequent UI updates driven by state changes, as it automates performance optimization and provides a declarative, "state-to-UI" programming model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When it's less relevant:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  For &lt;strong&gt;static websites or simple pages&lt;/strong&gt; where JavaScript-driven updates are rare. Direct DOM manipulation or server-side rendering is simpler and sufficient.&lt;/li&gt;
&lt;li&gt;  In performance-critical scenarios where you need &lt;strong&gt;absolute, manual control&lt;/strong&gt; over updates (e.g., a 60fps game canvas). The Virtual DOM's diffing process has a tiny overhead, and for these edge cases, you might opt for a framework that compiles to direct DOM updates (like Svelte) or manual management.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why you should care:&lt;/strong&gt; It abstracts away the manual, error-prone task of DOM performance tuning. You focus on &lt;em&gt;what&lt;/em&gt; the UI should look like for a given state, not the step-by-step instructions to change it.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Quick Example&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Consider a simple component that displays a counter. With &lt;strong&gt;direct Real DOM manipulation&lt;/strong&gt;, you might write:&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;// Manual, imperative update&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;counter&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;newCount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With a &lt;strong&gt;Virtual DOM-based framework&lt;/strong&gt; (like React), you write &lt;em&gt;declarative&lt;/em&gt; code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Declarative: Describe the UI for the current state&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"counter"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You only update the &lt;code&gt;count&lt;/code&gt; state variable. The framework's Virtual DOM engine detects that only the text content of this &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; changed. It then surgically updates &lt;em&gt;only&lt;/em&gt; that specific text node in the Real DOM, even if the rest of the component's HTML is more complex.&lt;/p&gt;

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

&lt;p&gt;The Virtual DOM is a &lt;strong&gt;performance optimization strategy&lt;/strong&gt; that lets you build dynamic UIs declaratively by batching and minimizing expensive browser updates. If you use React or similar frameworks, you're already leveraging it; understanding it helps you write better code and debug performance issues.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;For a deeper dive, check out the React team’s blog post on&lt;/em&gt; &lt;a href="https://reactjs.org/docs/reconciliation.html" rel="noopener noreferrer"&gt;&lt;em&gt;“Reconciliation.”&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>virtualdom</category>
      <category>realdom</category>
      <category>react</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>CSRF (Cross-Site Request Forgery) : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Tue, 07 Apr 2026 14:00:40 +0000</pubDate>
      <link>https://forem.com/hongster85/csrf-cross-site-request-forgery-understand-in-3-minutes-4hag</link>
      <guid>https://forem.com/hongster85/csrf-cross-site-request-forgery-understand-in-3-minutes-4hag</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Cross-Site Request Forgery (CSRF)&lt;/strong&gt; is an attack that tricks a user's browser into making an unwanted request to a website where they are already authenticated. You encounter this problem because modern web applications rely on browsers automatically sending stored credentials (like session cookies) with every request, which attackers can exploit to perform actions on a user's behalf without their consent. Imagine this: a user is logged into their bank in one tab, then clicks a link in a phishing email—that simple click could secretly trigger a request to transfer funds because the browser automatically attaches their valid bank session.&lt;/p&gt;

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

&lt;p&gt;A CSRF attack works by exploiting the trust a web application has in a user's browser. Here’s the simple breakdown of how it happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;The Setup:&lt;/strong&gt; A user logs into a legitimate site (e.g., &lt;code&gt;yourapp.com&lt;/code&gt;). The site issues a session cookie, which their browser stores and automatically sends with every subsequent request to &lt;code&gt;yourapp.com&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;The Trap:&lt;/strong&gt; The user, while still logged in, visits a malicious site (e.g., from a phishing email or a compromised ad). This site contains hidden, automatic code designed to trigger a request to &lt;code&gt;yourapp.com&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;The Forgery:&lt;/strong&gt; The user's browser, following the malicious site's instructions, makes a request to &lt;code&gt;yourapp.com&lt;/code&gt;. Crucially, it &lt;strong&gt;automatically includes the valid session cookie&lt;/strong&gt; from the legitimate login.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;The Result:&lt;/strong&gt; The target application (&lt;code&gt;yourapp.com&lt;/code&gt;) receives a request that looks perfectly legitimate—it has the correct session cookie—so it executes the action, like changing an email address or making a transaction, thinking the user intended it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of it like a &lt;strong&gt;forged signature stamp&lt;/strong&gt;. Your browser holds the stamp (your session cookie). A CSRF attack is like a malicious actor secretly placing a document under your stamped hand—the application sees your valid stamp on the request and processes it, even though you never intended to sign that document.&lt;/p&gt;

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

&lt;p&gt;You need to defend against CSRF &lt;strong&gt;whenever your web application performs state-changing actions&lt;/strong&gt; (POST, PUT, PATCH, DELETE requests) that rely on authentication cookies or other browser-automatic credentials. This includes actions like updating a profile, changing a password, or processing a financial transaction.&lt;/p&gt;

&lt;p&gt;You generally do &lt;strong&gt;not&lt;/strong&gt; need CSRF protection for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Public, read-only operations (GET requests, though GET should never change state anyway).&lt;/li&gt;
&lt;li&gt;  Stateless APIs that use tokens like JWTs in the &lt;code&gt;Authorization&lt;/code&gt; header (since browsers don’t automatically attach these headers to cross-site requests).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You should care because CSRF is a common and serious security flaw that can lead to compromised user accounts and data breaches. Modern frameworks (like Django, Rails, Spring Security, and Laravel) have built-in protections, but you must ensure they are properly enabled. If your app uses cookie-based sessions and has authenticated forms, CSRF defense is non-negotiable.&lt;/p&gt;

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

&lt;p&gt;Consider a simple, &lt;strong&gt;vulnerable&lt;/strong&gt; form in a banking app to transfer money:&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="c"&gt;&amp;lt;!-- Malicious site's code tricking a logged-in user --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&lt;/span&gt; &lt;span class="na"&gt;onload=&lt;/span&gt;&lt;span class="s"&gt;"document.forms[0].submit()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"https://yourbank.com/transfer"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"amount"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"1000"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"toAccount"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"ATTACKER_ACCOUNT"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the user is logged into &lt;code&gt;yourbank.com&lt;/code&gt;, visiting this malicious page would automatically submit the form and complete the transfer, as the browser sends the user's valid session cookie.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;protected&lt;/strong&gt; form includes a unique, secret CSRF token that the malicious site cannot guess or steal:&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="c"&gt;&amp;lt;!-- Your bank's legitimate form --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"https://yourbank.com/transfer"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"csrf_token"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"a9b3f7e2c1d5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"amount"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"toAccount"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Transfer&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server validates this token with every state-changing request. The attacker's forged request lacks the valid token and is rejected.&lt;/p&gt;

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

&lt;p&gt;The core defense is simple: &lt;strong&gt;for any state-changing request, verify that the user's browser intentionally sent the request, not just their credentials.&lt;/strong&gt; The standard method is to use a unique, unpredictable CSRF token issued by your server. For a deep dive on implementation, consult the &lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html" rel="noopener noreferrer"&gt;OWASP CSRF Prevention Cheat Sheet&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>csrf</category>
      <category>csrfattack</category>
      <category>websecurity</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Monitoring vs Observability : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Thu, 02 Apr 2026 14:00:54 +0000</pubDate>
      <link>https://forem.com/hongster85/monitoring-vs-observability-understand-in-3-minutes-1oeh</link>
      <guid>https://forem.com/hongster85/monitoring-vs-observability-understand-in-3-minutes-1oeh</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;Understanding &lt;strong&gt;monitoring&lt;/strong&gt; vs &lt;strong&gt;observability&lt;/strong&gt; is about knowing the difference between watching for known problems and being able to explore and diagnose unknown issues in your systems. You encounter this problem when your dashboards are green but users are still complaining, or when you get a generic "high latency" alert and spend hours digging through logs to find the root cause—you have monitoring, but you lack true observability.&lt;/p&gt;

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

&lt;p&gt;Think of it like car maintenance. &lt;strong&gt;Monitoring&lt;/strong&gt; is your dashboard warning lights: they alert you when predefined thresholds are crossed, like the check-engine light for a known error code. &lt;strong&gt;Observability&lt;/strong&gt;, however, is having a detailed diagnostic system and a mechanic's toolkit; it lets you ask arbitrary questions ("why is it making that &lt;em&gt;new&lt;/em&gt; noise?") and explore data you didn't necessarily pre-select to find the answer.&lt;/p&gt;

&lt;p&gt;Here’s the breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Monitoring&lt;/strong&gt; tells you &lt;em&gt;that&lt;/em&gt; something is wrong. It's a set of predetermined metrics and logs you watch. You set up alerts for CPU usage, error rates, or latency spikes. It's reactive and best for known failure modes. The core question it answers is, "Is the system behaving as expected?"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Observability&lt;/strong&gt; helps you understand &lt;em&gt;why&lt;/em&gt; something is wrong. It's a property of your system that allows you to understand its internal state from its external outputs. You achieve it by instrumenting your code to generate rich, correlated &lt;strong&gt;telemetry data&lt;/strong&gt;: metrics, logs, and &lt;strong&gt;distributed traces&lt;/strong&gt;. The core question it answers is, "What is happening, and why?"&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, monitoring is about watching a list of pre-defined gauges. Observability is about having the tools and data to debug any novel question that arises.&lt;/p&gt;

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

&lt;p&gt;You need robust &lt;strong&gt;monitoring&lt;/strong&gt; for all production systems to track system health and SLOs. It's your first line of defense. You invest in &lt;strong&gt;observability&lt;/strong&gt; when your system's complexity (like microservices, third-party APIs) makes failures unpredictable and hard to diagnose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to prioritize observability:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  When debugging requires stitching together events across multiple services.&lt;/li&gt;
&lt;li&gt;  When you need to understand user experience for specific flows, not just overall system health.&lt;/li&gt;
&lt;li&gt;  When "unknown-unknown" problems are causing significant outages or frustration.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When monitoring might suffice:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  For simple, monolithic applications with straightforward failure modes.&lt;/li&gt;
&lt;li&gt;  For tracking specific, well-understood business metrics (e.g., daily active users).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You should care because as systems grow, the time spent debugging "what's wrong" can dominate development. Observability shifts you from fighting fires to understanding your system's behavior, leading to faster resolutions and more stable software.&lt;/p&gt;

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

&lt;p&gt;Imagine a user reports that their payment failed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;With &lt;strong&gt;monitoring&lt;/strong&gt;, you might see an alert that the &lt;code&gt;payment-service&lt;/code&gt; error rate is at 5%. You check the service logs and see a &lt;code&gt;DatabaseConnectionException&lt;/code&gt;. You've identified the symptom.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;With &lt;strong&gt;observability&lt;/strong&gt;, you examine a &lt;strong&gt;distributed trace&lt;/strong&gt; of that specific user's request. The trace shows the request journey: from the &lt;code&gt;web-api&lt;/code&gt;, to the &lt;code&gt;auth-service&lt;/code&gt;, to the &lt;code&gt;payment-service&lt;/code&gt;. You see that the &lt;code&gt;payment-service&lt;/code&gt; call is indeed failing, but the correlated logs and metrics reveal the &lt;em&gt;root cause&lt;/em&gt;: the &lt;code&gt;auth-service&lt;/code&gt; is timing out first, causing the payment service's database connection pool to be exhausted for subsequent requests.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The example shows how observability tools connect data points across services to pinpoint a root cause that was non-obvious from isolated monitoring.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Shift your mindset from just setting alerts (monitoring) to instrumenting your code to enable exploration (observability), especially as your systems become more complex.&lt;/strong&gt; For a deeper dive into the philosophy, read Charity Majors' post &lt;a href="https://www.honeycomb.io/blog/observability-is-a-many-splendored-thing" rel="noopener noreferrer"&gt;Observability is a Many-Splendored Thing&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>monitoring</category>
      <category>observability</category>
      <category>telemetrydata</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Rate Limiting : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Tue, 31 Mar 2026 14:00:44 +0000</pubDate>
      <link>https://forem.com/hongster85/rate-limiting-understand-in-3-minutes-14g</link>
      <guid>https://forem.com/hongster85/rate-limiting-understand-in-3-minutes-14g</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Rate limiting&lt;/strong&gt; is a technique that controls how many requests a user or system can make to a server within a specific timeframe. You encounter this problem directly when an API rejects your request with an error like "429 Too Many Requests" or "Rate Limit Exceeded." It affects you whether you're &lt;em&gt;consuming&lt;/em&gt; an API that's throttling your app's calls, or &lt;em&gt;building&lt;/em&gt; a service that's being overwhelmed by too much traffic, a buggy loop, or even a malicious attack.&lt;/p&gt;

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

&lt;p&gt;Think of rate limiting like a &lt;strong&gt;leaky bucket&lt;/strong&gt;. A new, empty bucket can hold a certain number of tokens (your request &lt;strong&gt;allowance&lt;/strong&gt;). Every time you make a request, you take a token out. Tokens &lt;strong&gt;leak back in&lt;/strong&gt; at a steady rate (your &lt;strong&gt;replenishment rate&lt;/strong&gt;). If you try to make a request when the bucket is empty, you’re denied until a token leaks back in.&lt;/p&gt;

&lt;p&gt;Under the hood, a simple rate limiter checks three key things for each incoming request:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Who:&lt;/strong&gt; It identifies the requester using an API key, IP address, or user ID.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;How Many:&lt;/strong&gt; It checks a counter for that requester against a predefined limit (e.g., 100 requests).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;In What Time Window:&lt;/strong&gt; It enforces that limit within a specific period (e.g., per minute).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the count is under the limit, the request proceeds and the counter increments. If the limit is hit, the server typically responds with an &lt;strong&gt;HTTP 429 status code&lt;/strong&gt; and often includes headers telling you when to try again.&lt;/p&gt;

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

&lt;p&gt;You should use rate limiting on any service where you need to &lt;strong&gt;ensure availability, protect resources, or enforce fair usage.&lt;/strong&gt; This is critical for public APIs, login endpoints, and expensive database operations.&lt;/p&gt;

&lt;p&gt;You might &lt;em&gt;not&lt;/em&gt; need to implement it for internal microservices communicating within a trusted network where traffic patterns are predictable and controlled, though it's still a good defensive practice.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Protecting Third-Party APIs:&lt;/strong&gt; When using a service like Stripe or Twitter, you must respect their limits to avoid having your integration shut down.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Preventing Abuse:&lt;/strong&gt; Throttling login attempts or password resets to stop brute-force attacks.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Managing Infrastructure Load:&lt;/strong&gt; Ensuring one overly chatty client or a misconfigured job doesn't drown your database or application servers.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You should care because rate limiting is a fundamental tool for building &lt;strong&gt;resilient and secure systems.&lt;/strong&gt; It's not just about saying "no"—it's about saying "yes, reliably, to everyone."&lt;/p&gt;

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

&lt;p&gt;Imagine a login endpoint with a limit of 5 attempts per minute. The server tracks attempts by IP address.&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;# Pseudocode logic for the /login endpoint
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_login_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip_address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;login_attempts:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ip_address&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;current_attempts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;incr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Increment counter
&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;current_attempts&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Set expiry on first attempt
&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;current_attempts&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&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;Too many attempts. Try again in 60 seconds.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;429&lt;/span&gt;

    &lt;span class="c1"&gt;# ... proceed to validate password ...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example shows the core pattern: &lt;strong&gt;increment, check, and reject.&lt;/strong&gt; The &lt;code&gt;429&lt;/code&gt; status code clearly communicates the limit to the client, and using a store like Redis with an expiry automates the "per minute" window.&lt;/p&gt;

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

&lt;p&gt;Remember that &lt;strong&gt;rate limiting is a safety feature, not just a restriction&lt;/strong&gt;; it protects your system's stability and fairness for all users. For a deeper dive into algorithms and implementation, check out the &lt;a href="https://cloud.google.com/architecture/rate-limiting-strategies-techniques" rel="noopener noreferrer"&gt;Google Cloud Architecture Center's guide on rate limiting&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ratelimiting</category>
      <category>leakybucket</category>
      <category>http429</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Webhooks : Understand in 3 Minutes</title>
      <dc:creator>Hongster</dc:creator>
      <pubDate>Thu, 26 Mar 2026 14:00:46 +0000</pubDate>
      <link>https://forem.com/hongster85/webhooks-understand-in-3-minutes-3i0a</link>
      <guid>https://forem.com/hongster85/webhooks-understand-in-3-minutes-3i0a</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Webhooks are automated messages sent from apps when something happens.&lt;/strong&gt; They're the solution to the frustrating and inefficient "Are we there yet?" problem in software integrations. Instead of your application constantly asking (polling) another service for updates—like checking every 10 minutes for a new payment or a completed form submission—webhooks make the other service call you the instant the event occurs. Think of the last time you built a feature that needed real-time data from another platform; webhooks are how you get that data without wasting resources and introducing delay.&lt;/p&gt;

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

&lt;p&gt;At its core, a webhook is a simple callback over HTTP. It’s a way for App A (the provider) to notify your App B (the receiver) about an event by making an HTTP POST request to a URL you provide.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;You Give a URL:&lt;/strong&gt; You register a public endpoint (e.g., &lt;code&gt;https://yourapp.com/webhooks/payment-processed&lt;/code&gt;) with a service that supports webhooks (like Stripe or GitHub).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;They Call It:&lt;/strong&gt; When a specified event happens in their system (e.g., &lt;code&gt;invoice.paid&lt;/code&gt; or &lt;code&gt;push&lt;/code&gt;), their server creates a payload of data about that event and sends it as an HTTP POST request to your endpoint.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;You Act on It:&lt;/strong&gt; Your server receives the request, verifies it’s legitimate, parses the data, and triggers the corresponding business logic in your app.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A simple analogy is &lt;strong&gt;"reverse API."&lt;/strong&gt; With a normal API, you call them. With a webhook, they call you. It's like asking a restaurant to text you when your table is ready (webhook) versus walking back to the host stand every two minutes to ask (polling).&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Use webhooks when you need near real-time, event-driven updates from an external service.&lt;/strong&gt; They are ideal for automating workflows, syncing data between systems, and triggering immediate actions. Common use cases include processing payments (Stripe sends you a webhook on success), updating a database when a user signs up in another app, or triggering a CI/CD build when code is pushed to a repository (like GitHub Actions).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Avoid webhooks&lt;/strong&gt; for low-volume events where a simple scheduled job is sufficient, or when the client application (like a mobile app) needs the update, as you can't reliably send a webhook to a device that might be offline. In those cases, polling or a persistent connection (like WebSockets) might be a better fit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You should care&lt;/strong&gt; because webhooks are the backbone of modern, decoupled, and efficient third-party integrations. They save server resources, reduce latency, and enable event-driven architectures.&lt;/p&gt;

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

&lt;p&gt;Imagine you need to know when a customer's subscription renews via Stripe. Instead of polling their API, you'd set up a webhook endpoint:&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;// A simple Express.js endpoint for a Stripe 'customer.subscription.updated' webhook&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;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/webhooks/stripe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&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;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&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;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Contains the subscription data&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;customer.subscription.updated&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subscription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Update YOUR database with the new subscription status&lt;/span&gt;
    &lt;span class="nf"&gt;updateUserSubscription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;received&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example demonstrates the passive nature of webhooks. Your code sits idle, waiting for Stripe to deliver the event. When they do, you immediately update your system's state, keeping it perfectly in sync.&lt;/p&gt;

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

&lt;p&gt;Think of webhooks as a subscription service for events: you give a service your number (URL), and they call you only when there's news, eliminating wasteful polling and enabling real-time automation. For an excellent deep dive on implementation patterns, check out &lt;a href="https://webhooks.fyi" rel="noopener noreferrer"&gt;Webhooks.fyi&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webhooks</category>
      <category>softwareintegrations</category>
      <category>eventdriven</category>
      <category>abotwrotethis</category>
    </item>
  </channel>
</rss>
