<?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: Bhupesh Chandra Joshi</title>
    <description>The latest articles on Forem by Bhupesh Chandra Joshi (@bhupeshchandrajoshi).</description>
    <link>https://forem.com/bhupeshchandrajoshi</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%2F1931767%2Ffb73ef56-faf6-4992-9ee8-6ce544b122b6.jpeg</url>
      <title>Forem: Bhupesh Chandra Joshi</title>
      <link>https://forem.com/bhupeshchandrajoshi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/bhupeshchandrajoshi"/>
    <language>en</language>
    <item>
      <title>URL Parameters vs Query Strings in Express.js: A Practical Guide</title>
      <dc:creator>Bhupesh Chandra Joshi</dc:creator>
      <pubDate>Fri, 08 May 2026 17:18:48 +0000</pubDate>
      <link>https://forem.com/bhupeshchandrajoshi/url-parameters-vs-query-strings-in-expressjs-a-practical-guide-2nk0</link>
      <guid>https://forem.com/bhupeshchandrajoshi/url-parameters-vs-query-strings-in-expressjs-a-practical-guide-2nk0</guid>
      <description>&lt;p&gt;&lt;em&gt;Master route params and query strings for cleaner, more RESTful Node.js APIs&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;When building APIs with &lt;strong&gt;Express.js&lt;/strong&gt;, handling dynamic data from URLs is fundamental. Two common mechanisms—&lt;strong&gt;URL Parameters&lt;/strong&gt; (route params) and &lt;strong&gt;Query Strings&lt;/strong&gt; (query params)—often confuse beginners. Understanding when and how to use each leads to more intuitive, performant, and maintainable APIs.&lt;/p&gt;

&lt;p&gt;In this practical guide, you'll learn the differences, how to access them in Express, real-world examples, and best practices. Let's dive in.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. What are URL Parameters (Route Params)?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;URL Parameters&lt;/strong&gt; are dynamic segments of the URL path itself. They act as &lt;strong&gt;identifiers&lt;/strong&gt; for a specific resource.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Defined in your route using a colon (&lt;code&gt;:&lt;/code&gt;) prefix.&lt;/li&gt;
&lt;li&gt;Part of the URL structure, not optional by default.&lt;/li&gt;
&lt;li&gt;Ideal for targeting a unique resource.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example URL:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;https://api.example.com/users/123&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here, &lt;code&gt;123&lt;/code&gt; is the user ID.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In Express route:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/users/:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. What are Query Strings (Query Parameters)?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Query Strings&lt;/strong&gt; are key-value pairs appended to the URL after a question mark (&lt;code&gt;?&lt;/code&gt;). They are used for &lt;strong&gt;filters, modifiers, sorting, pagination&lt;/strong&gt;, or optional data.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not part of the core route path.&lt;/li&gt;
&lt;li&gt;Multiple parameters separated by &lt;code&gt;&amp;amp;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Optional and order-independent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example URL:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;https://api.example.com/users?role=admin&amp;amp;limit=10&amp;amp;sort=desc&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here, we're filtering users by role, limiting results, and sorting them.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Key Differences: Params vs Query
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;URL Parameters (Route Params)&lt;/th&gt;
&lt;th&gt;Query Strings&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Position in URL&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Part of the path (e.g., &lt;code&gt;/users/123&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;After &lt;code&gt;?&lt;/code&gt; (e.g., &lt;code&gt;?page=2&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Purpose&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Identify a specific resource&lt;/td&gt;
&lt;td&gt;Filter, sort, paginate, or modify&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Required?&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Usually yes (defines the route)&lt;/td&gt;
&lt;td&gt;Always optional&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Caching&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Better for unique resources&lt;/td&gt;
&lt;td&gt;Can complicate caching&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SEO/Readability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cleaner for resource IDs&lt;/td&gt;
&lt;td&gt;Good for search/filter states&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Access in Express&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;req.params&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;req.query&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Multiple values&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;One per named param&lt;/td&gt;
&lt;td&gt;Easy (e.g., &lt;code&gt;?tags=js&amp;amp;tags=node&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Params&lt;/strong&gt; answer &lt;em&gt;"Which resource?"&lt;/em&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Query&lt;/strong&gt; answers &lt;em&gt;"How should I process/filter it?"&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Accessing URL Parameters in Express.js
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Single parameter&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/users/:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;res&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="nx"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Multiple parameters&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/users/:userId/posts/:postId&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;postId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;postId&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// With regex constraint (optional)&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/users/:id(&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;d+)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Only matches numeric IDs&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  5. Accessing Query Strings in Express.js
&lt;/h3&gt;

&lt;p&gt;Express automatically parses query strings into &lt;code&gt;req.query&lt;/code&gt; (no extra middleware needed for basic cases).&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="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/search&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;page&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="nx"&gt;limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sort&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
  &lt;span class="c1"&gt;// Example: { q: 'nodejs', page: '1', limit: '10', sort: 'desc' }&lt;/span&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;pagination&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;sort&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;Tip:&lt;/strong&gt; Query values are always strings. Convert numbers/booleans as needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. When to Use Params vs Query Strings
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Use Route Parameters when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fetching a &lt;strong&gt;specific resource&lt;/strong&gt; by ID (user profile, product detail, order).&lt;/li&gt;
&lt;li&gt;The value is &lt;strong&gt;essential&lt;/strong&gt; to identify the resource.&lt;/li&gt;
&lt;li&gt;Examples:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GET /users/:username&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /products/:productId&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DELETE /posts/:postId&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use Query Parameters when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Filtering&lt;/strong&gt; or searching a collection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pagination&lt;/strong&gt; (&lt;code&gt;page&lt;/code&gt;, &lt;code&gt;limit&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sorting&lt;/strong&gt; or additional modifiers.&lt;/li&gt;
&lt;li&gt;Optional configurations.&lt;/li&gt;
&lt;li&gt;Examples:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GET /users?role=admin&amp;amp;active=true&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /products?category=electronics&amp;amp;price_lt=100&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /search?q=express&amp;amp;limit=20&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Hybrid Example (Best of Both):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Get posts for a specific user with filters&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/users/:userId/posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&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;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;limit&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Practical Tips &amp;amp; Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Keep routes &lt;strong&gt;RESTful&lt;/strong&gt;: Use params for nouns/resources, query for actions/filters.&lt;/li&gt;
&lt;li&gt;Validate inputs (use libraries like &lt;code&gt;express-validator&lt;/code&gt; or &lt;code&gt;zod&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;For complex query handling, consider middleware.&lt;/li&gt;
&lt;li&gt;Be consistent across your API.&lt;/li&gt;
&lt;li&gt;Remember: Query strings are visible in logs, URLs, and browser history—avoid sensitive data.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Useful npm Packages
&lt;/h3&gt;

&lt;p&gt;Here are some helpful packages to enhance param and query handling:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;express-validator&lt;/code&gt;&lt;/strong&gt; — Robust validation and sanitization for both &lt;code&gt;req.params&lt;/code&gt; and &lt;code&gt;req.query&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;query-string&lt;/code&gt;&lt;/strong&gt; — Advanced parsing/stringifying of query strings (great for complex cases or frontend).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;express-normalize-query-params-middleware&lt;/code&gt;&lt;/strong&gt; — Normalizes and validates query parameters automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;zod&lt;/code&gt;&lt;/strong&gt; + custom middleware — Modern schema validation (very popular in 2025+).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;router&lt;/code&gt;&lt;/strong&gt; (built-in) — Use &lt;code&gt;express.Router()&lt;/code&gt; for modular route organization with params.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Installation example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;express-validator zod query-string
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Mastering &lt;strong&gt;URL parameters&lt;/strong&gt; and &lt;strong&gt;query strings&lt;/strong&gt; is key to building scalable Express.js APIs. Treat params as &lt;strong&gt;resource identifiers&lt;/strong&gt; and queries as &lt;strong&gt;filters/modifiers&lt;/strong&gt;—this mental model will guide most of your routing decisions.&lt;/p&gt;

&lt;p&gt;Start simple, stay consistent, and your API endpoints will feel natural to both frontend developers and other backend teams.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What do you think?&lt;/strong&gt; Have you faced tricky decisions between params and queries in your projects? Drop your thoughts in the comments!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Happy coding! 🚀&lt;/em&gt;&lt;/p&gt;




</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Storing Uploaded Files and Serving Them in Express</title>
      <dc:creator>Bhupesh Chandra Joshi</dc:creator>
      <pubDate>Fri, 08 May 2026 15:25:45 +0000</pubDate>
      <link>https://forem.com/bhupeshchandrajoshi/storing-uploaded-files-and-serving-them-in-express-2jh5</link>
      <guid>https://forem.com/bhupeshchandrajoshi/storing-uploaded-files-and-serving-them-in-express-2jh5</guid>
      <description>&lt;p&gt;&lt;strong&gt;Storing Uploaded Files and Serving Them in Express.js&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Hey folks! If you're building any real-world Node.js app—whether it's a social platform, marketplace, blog with image uploads, or SaaS—you'll eventually need to handle file uploads. Today we'll demystify &lt;strong&gt;where files actually live&lt;/strong&gt;, how to serve them efficiently with Express, and how to do it without shooting yourself in the foot.&lt;/p&gt;

&lt;p&gt;I’ve shipped features which can handle millions of uploads. Let’s make this intuitive.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Where Do Uploaded Files Actually Get Stored?
&lt;/h3&gt;

&lt;p&gt;When a user uploads a file (image, PDF, video, etc.), your server receives it as a stream or buffer. You decide where to persist it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common options:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Local filesystem&lt;/strong&gt; ( &lt;code&gt;./uploads/&lt;/code&gt; folder on your server)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud object storage&lt;/strong&gt; (AWS S3, Google Cloud Storage, Cloudflare R2, Azure Blob)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database&lt;/strong&gt; (rare for large files — not recommended except for tiny blobs)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For learning and small/medium apps → &lt;strong&gt;local storage&lt;/strong&gt; is perfect. For production at scale → &lt;strong&gt;external storage&lt;/strong&gt; wins.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Local Storage vs External Storage (Mental Model)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Local Storage (Development + Small Apps)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pros: Simple, fast, no extra cost, easy debugging&lt;/li&gt;
&lt;li&gt;Cons: Doesn't scale horizontally (multiple servers = sync nightmare), server disk fills up, backups are manual, not CDN-friendly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;External/Cloud Storage&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pros: Infinite scalability, built-in CDN, high durability, pay-as-you-go, works beautifully with multiple app instances&lt;/li&gt;
&lt;li&gt;Cons: Slight latency, costs money at scale, more complex setup initially&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;My rule of thumb (battle-tested):&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Start with local + Multer. When you need to scale or go production, switch the storage engine (you can abstract it nicely).&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Setting Up Folder-Based Storage Structure
&lt;/h3&gt;

&lt;p&gt;Here's a clean, scalable folder structure I recommend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;project-root/
├── uploads/                  &lt;span class="c"&gt;# .gitignore this!&lt;/span&gt;
│   ├── images/
│   ├── documents/
│   ├── avatars/
│   └── temp/                 &lt;span class="c"&gt;# for processing&lt;/span&gt;
├── public/
│   └── assets/               &lt;span class="c"&gt;# (optional - built assets)&lt;/span&gt;
├── src/
│   ├── controllers/
│   ├── routes/
│   ├── middleware/
│   └── utils/storage.js      &lt;span class="c"&gt;# abstraction layer&lt;/span&gt;
├── package.json
└── .gitignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pro tip:&lt;/strong&gt; Never store uploads in the root or &lt;code&gt;public&lt;/code&gt; directly during upload. Process first, then move.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Serving Static Files in Express (The Magic)
&lt;/h3&gt;

&lt;p&gt;Express has a built-in middleware for this: &lt;code&gt;express.static()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app.js or server.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Serve static files&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/uploads&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;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uploads&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;        &lt;span class="c1"&gt;// Basic&lt;/span&gt;
&lt;span class="c1"&gt;// or with options&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/uploads&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;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uploads&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;maxAge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c1"&gt;// Browser caching&lt;/span&gt;
  &lt;span class="na"&gt;etag&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="na"&gt;lastModified&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now any file at &lt;code&gt;uploads/images/cat.jpg&lt;/code&gt; becomes accessible at:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://yoursite.com/uploads/images/cat.jpg&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Brain-friendly flow diagram (text version):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client Upload Request 
        ↓ (multipart/form-data)
Express + Multer Middleware
        ↓ (validate + save to disk)
uploads/images/abc123.jpg
        ↓
express.static middleware
        ↓
Client accesses via URL → served directly by Express
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Complete Upload Example with Multer (pnpm style)
&lt;/h3&gt;

&lt;p&gt;I love &lt;strong&gt;pnpm&lt;/strong&gt; — it's fast, disk-efficient, and has strict dependency handling. Here's how I set it up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm add multer
pnpm add &lt;span class="nt"&gt;-D&lt;/span&gt; @types/multer   &lt;span class="c"&gt;# if using TypeScript&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// middleware/upload.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;multer&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;multer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fileURLToPath&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;__filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fileURLToPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;__dirname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__filename&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;storage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;multer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;diskStorage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&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;uploadPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../uploads/images&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// ensure directory exists (use fs-extra in prod)&lt;/span&gt;
    &lt;span class="nf"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;uploadPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&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;uniqueSuffix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&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;-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;E9&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;uniqueSuffix&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;originalname&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// File filter - security first!&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileFilter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&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;allowedTypes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/jpeg|jpg|png|gif|webp|pdf/&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;extname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;allowedTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;originalname&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&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;mimetype&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;allowedTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mimetype&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;extname&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;mimetype&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Only images and PDFs are allowed!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;upload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;multer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;fileSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;// 5MB&lt;/span&gt;
  &lt;span class="nx"&gt;fileFilter&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Route usage:&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="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;/api/upload&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;single&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;image&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;file&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&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;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No file uploaded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;://&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;host&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;/uploads/images/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;res&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;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Upload successful&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fileUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. Accessing Uploaded Files via URL
&lt;/h3&gt;

&lt;p&gt;Once served via &lt;code&gt;express.static&lt;/code&gt;, files are publicly accessible. You can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Return full URLs from your APIs&lt;/li&gt;
&lt;li&gt;Use them directly in &lt;code&gt;&amp;lt;img src="..."&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Serve with CDN later by changing the base URL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Advanced tip:&lt;/strong&gt; Create a utility that generates URLs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getFileUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filename&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;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; 
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`https://cdn.yoursite.com/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BASE_URL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/uploads/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  7. Security Considerations (Don't Skip This!)
&lt;/h3&gt;

&lt;p&gt;This is where most juniors get hacked:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Always validate file types&lt;/strong&gt; (both extension + mime)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Set file size limits&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rename files&lt;/strong&gt; (never trust &lt;code&gt;originalname&lt;/code&gt; — can contain malicious paths)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scan for malware&lt;/strong&gt; (ClamAV or cloud service) in production&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't allow executable files&lt;/strong&gt; (.exe, .php, .js, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use helmet.js&lt;/strong&gt; + CSP headers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rate limit uploads&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Store outside of your main app directory&lt;/strong&gt; if possible&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set proper file permissions&lt;/strong&gt; (not 777!)
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm add helmet express-rate-limit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Bonus: Production-Ready Abstraction
&lt;/h3&gt;

&lt;p&gt;Create &lt;code&gt;src/utils/storage.js&lt;/code&gt; early so you can swap between local, S3, R2 later with minimal changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary (The Takeaway)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Start simple with local &lt;code&gt;uploads/&lt;/code&gt; folder + &lt;code&gt;express.static&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;Multer&lt;/strong&gt; for robust handling&lt;/li&gt;
&lt;li&gt;Always think about the &lt;strong&gt;URL&lt;/strong&gt; your files will live at&lt;/li&gt;
&lt;li&gt;Security is not optional&lt;/li&gt;
&lt;li&gt;Design for future migration to cloud storage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Recommended pnpm stack for uploads:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm add multer express helmet express-rate-limit
pnpm add &lt;span class="nt"&gt;-D&lt;/span&gt; nodemon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Would you like the &lt;strong&gt;TypeScript version&lt;/strong&gt;, &lt;strong&gt;S3 integration guide&lt;/strong&gt;, or &lt;strong&gt;Multer with multiple files + progress tracking&lt;/strong&gt; next? Drop your thoughts below.&lt;/p&gt;

&lt;p&gt;Happy coding! 🚀&lt;/p&gt;




</description>
      <category>webdev</category>
      <category>productivity</category>
      <category>javascript</category>
      <category>web3</category>
    </item>
    <item>
      <title>Sessions vs JWT vs Cookies: Understanding Authentication Approaches</title>
      <dc:creator>Bhupesh Chandra Joshi</dc:creator>
      <pubDate>Fri, 08 May 2026 15:18:50 +0000</pubDate>
      <link>https://forem.com/bhupeshchandrajoshi/sessions-vs-jwt-vs-cookies-understanding-authentication-approaches-ofk</link>
      <guid>https://forem.com/bhupeshchandrajoshi/sessions-vs-jwt-vs-cookies-understanding-authentication-approaches-ofk</guid>
      <description>&lt;p&gt;&lt;strong&gt;Auth Wars: Sessions, JWTs &amp;amp; Cookies – The Love Triangle That Keeps Your Backend Awake at Night&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Written by two devs who’ve been ghosted by auth more times than we care to admit. One writes code, the other writes so your brain doesn’t explode.&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  The Eternal Question Every Dev Asks at 2 AM
&lt;/h3&gt;

&lt;p&gt;You just built a beautiful app. Users are ready. Then comes the dreaded question:  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“How do we remember who this person is?”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Suddenly you’re drowning in Stack Overflow tabs, comparing &lt;strong&gt;Sessions&lt;/strong&gt;, &lt;strong&gt;JWTs&lt;/strong&gt;, and &lt;strong&gt;Cookies&lt;/strong&gt; like they’re contestants on The Bachelor.  &lt;/p&gt;

&lt;p&gt;Don’t worry. Grab your coffee (or energy drink), and let’s make this ridiculously simple, mildly hilarious, and actually useful.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. Cookies: The clingy ex who remembers everything
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Cookies&lt;/strong&gt; are tiny text files that the browser stores and sends back with every request to the same domain.  &lt;/p&gt;

&lt;p&gt;Think of them as the sticky note your browser sticks on your forehead: “This is GrokUser123. Be nice to him.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key traits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatically sent with requests (no manual work)&lt;/li&gt;
&lt;li&gt;Can be &lt;code&gt;httpOnly&lt;/code&gt; (JS can’t touch them → safer from XSS)&lt;/li&gt;
&lt;li&gt;Limited size (~4KB)&lt;/li&gt;
&lt;li&gt;Can be session cookies (gone when browser closes) or persistent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pro tip:&lt;/strong&gt; Cookies are &lt;em&gt;not&lt;/em&gt; authentication. They’re just the delivery guy. What they carry is what matters.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Sessions: The loyal butler who knows your entire life story
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Session-based auth&lt;/strong&gt; = Server keeps all the user data (userId, roles, last login, favorite meme, etc.) in memory/database.  &lt;/p&gt;

&lt;p&gt;The browser only holds a tiny &lt;strong&gt;session ID&lt;/strong&gt; (usually in a cookie).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flow (imagine a cute diagram here):&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User logs in → Server creates session record → Sends session ID cookie&lt;/li&gt;
&lt;li&gt;Every request → Browser sends cookie → Server looks up the full session&lt;/li&gt;
&lt;li&gt;“Ah yes, this is GrokUser123. He’s allowed to delete posts.”&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Stateful authentication&lt;/strong&gt; – the server has &lt;em&gt;state&lt;/em&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. JWT (JSON Web Tokens): The stateless daredevil
&lt;/h3&gt;

&lt;p&gt;JWT is like a concert wristband with all your VIP details written on it in fancy encrypted ink.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Structure:&lt;/strong&gt; &lt;code&gt;header.payload.signature&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Inside the payload: user ID, roles, expiry, “I love cats” flag, etc.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;User logs in → Server creates JWT → Sends it back (usually in cookie or Authorization header)&lt;/li&gt;
&lt;li&gt;Every request → Client sends JWT → Server verifies signature → Trusts the data inside&lt;/li&gt;
&lt;li&gt;No database lookup needed. Boom.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Stateless authentication&lt;/strong&gt; – the server doesn’t remember you. It just checks your fancy ID.&lt;/p&gt;




&lt;h3&gt;
  
  
  Stateful vs Stateless – The Philosophical Battle
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Stateful (Sessions)&lt;/th&gt;
&lt;th&gt;Stateless (JWT)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Server Memory&lt;/td&gt;
&lt;td&gt;Remembers everything&lt;/td&gt;
&lt;td&gt;Remembers nothing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scaling&lt;/td&gt;
&lt;td&gt;Needs sticky sessions or shared DB&lt;/td&gt;
&lt;td&gt;Scales like crazy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance&lt;/td&gt;
&lt;td&gt;One DB lookup per request&lt;/td&gt;
&lt;td&gt;Just crypto verification&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Logout&lt;/td&gt;
&lt;td&gt;Just delete session&lt;/td&gt;
&lt;td&gt;Have to wait for expiry or use blacklist&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Token Size&lt;/td&gt;
&lt;td&gt;Tiny (just ID)&lt;/td&gt;
&lt;td&gt;Can get chunky&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Revocation&lt;/td&gt;
&lt;td&gt;Easy&lt;/td&gt;
&lt;td&gt;Annoying (blacklist or short expiry)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  Sessions vs JWT – The Ultimate Showdown
&lt;/h3&gt;

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

&lt;ul&gt;
&lt;li&gt;You have a small/medium app&lt;/li&gt;
&lt;li&gt;You need instant logout across all devices&lt;/li&gt;
&lt;li&gt;You want to store extra user data server-side&lt;/li&gt;
&lt;li&gt;You’re building something internal or behind a corporate firewall&lt;/li&gt;
&lt;li&gt;You value simplicity over horizontal scaling&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;You’re building a mobile app + web app (same token everywhere)&lt;/li&gt;
&lt;li&gt;You need to scale to millions of users&lt;/li&gt;
&lt;li&gt;You have microservices talking to each other&lt;/li&gt;
&lt;li&gt;You’re okay with short-lived tokens + refresh tokens&lt;/li&gt;
&lt;li&gt;You want to be the cool distributed systems kid&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Real talk:&lt;/strong&gt; Many modern apps use &lt;strong&gt;both&lt;/strong&gt;. JWT for API calls + httpOnly cookie to store it. Hybrid gang rise up.&lt;/p&gt;




&lt;h3&gt;
  
  
  Cookies in All This Drama
&lt;/h3&gt;

&lt;p&gt;Cookies are the &lt;strong&gt;messenger&lt;/strong&gt;, not the message.&lt;/p&gt;

&lt;p&gt;Best practice in 2026:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Store session ID &lt;strong&gt;or&lt;/strong&gt; JWT in an &lt;code&gt;httpOnly&lt;/code&gt;, &lt;code&gt;Secure&lt;/code&gt;, &lt;code&gt;SameSite=Strict&lt;/code&gt; cookie&lt;/li&gt;
&lt;li&gt;This protects you from most XSS and CSRF nonsense&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Libraries That Make Life Stupidly Easy (pnpm edition)
&lt;/h3&gt;

&lt;p&gt;Stop writing auth from scratch. Your future self will thank you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For Express/Node:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# The holy trinity&lt;/span&gt;
pnpm &lt;span class="nb"&gt;install &lt;/span&gt;express-session jsonwebtoken cookie-parser

&lt;span class="c"&gt;# Bonus: Secure cookie settings made easy&lt;/span&gt;
pnpm &lt;span class="nb"&gt;install &lt;/span&gt;helmet cors

&lt;span class="c"&gt;# If you want refresh tokens + best practices&lt;/span&gt;
pnpm &lt;span class="nb"&gt;install &lt;/span&gt;next-auth@beta   &lt;span class="c"&gt;# (for Next.js)&lt;/span&gt;
&lt;span class="c"&gt;# or&lt;/span&gt;
pnpm &lt;span class="nb"&gt;install &lt;/span&gt;lucia            &lt;span class="c"&gt;# Beautiful, modern session auth&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;My current favorite combo:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lucia&lt;/strong&gt; for sessions (feels like it was written by a poet)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;jsonwebtoken&lt;/strong&gt; + httpOnly cookies for JWT APIs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drizzle&lt;/strong&gt; or &lt;strong&gt;Prisma&lt;/strong&gt; to store sessions when needed&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Quick Decision Cheat Sheet
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Solo indie hacker / small team?&lt;/strong&gt; → Sessions + httpOnly cookie&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Building SaaS with mobile app?&lt;/strong&gt; → JWT + Refresh tokens&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise with strict security?&lt;/strong&gt; → Sessions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Microservices everywhere?&lt;/strong&gt; → JWT (or OAuth2 + OpenID Connect, but that’s another blog)&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Final Wisdom From Two Sleep-Deprived Devs
&lt;/h3&gt;

&lt;p&gt;There is &lt;strong&gt;no universally correct&lt;/strong&gt; answer.  &lt;/p&gt;

&lt;p&gt;The correct answer is: &lt;em&gt;the one that solves your current problem without creating three new ones.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And remember:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Cookies deliver the message.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Sessions remember the user.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;JWTs flex on the blockchain kids.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now go build something awesome — and for the love of all that is holy, don’t store passwords in plain text.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Got questions or stories about auth gone wrong? Drop them in the comments. We collect these like Pokémon cards.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; #webdev #authentication #backend #nodejs #jwt #sessions #cookies #learnthecoolway&lt;/p&gt;

</description>
      <category>learnthecoolway</category>
      <category>architecture</category>
      <category>discuss</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Async Code in Node.js: Callbacks and Promises</title>
      <dc:creator>Bhupesh Chandra Joshi</dc:creator>
      <pubDate>Fri, 08 May 2026 15:11:37 +0000</pubDate>
      <link>https://forem.com/bhupeshchandrajoshi/async-code-in-nodejs-callbacks-and-promises-3f6c</link>
      <guid>https://forem.com/bhupeshchandrajoshi/async-code-in-nodejs-callbacks-and-promises-3f6c</guid>
      <description>&lt;p&gt;&lt;strong&gt;Async Code in Node.js: Callbacks and Promises&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Node.js is built on an event-driven, non-blocking I/O model. This design choice makes it exceptionally performant for I/O-heavy applications like web servers, APIs, and real-time services. But to truly master Node.js, you must understand how asynchronous code works—starting with the classic &lt;strong&gt;callbacks&lt;/strong&gt; and evolving to the much cleaner &lt;strong&gt;Promises&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this comprehensive guide, we’ll explore why async code is essential, how callbacks work (and where they fail), and how Promises solve those problems with far better readability and maintainability.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. Why Async Code Exists in Node.js
&lt;/h3&gt;

&lt;p&gt;Imagine a traditional server built in a language like PHP or Python (in synchronous mode). When it needs to read a file or query a database, the entire thread blocks until the operation completes. During that wait, the server can’t handle other requests. This leads to poor scalability.&lt;/p&gt;

&lt;p&gt;Node.js takes a different approach. It uses &lt;strong&gt;libuv&lt;/strong&gt; under the hood to offload I/O operations to the operating system or thread pool. The main JavaScript thread remains free to handle other tasks while waiting for I/O.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key takeaway&lt;/strong&gt;: Async code in Node.js isn’t optional—it’s fundamental to its performance and scalability.&lt;/p&gt;

&lt;p&gt;A perfect real-world example is &lt;strong&gt;reading files&lt;/strong&gt; from the filesystem.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Callback-based Async Execution
&lt;/h3&gt;

&lt;p&gt;Let’s start with a practical scenario: You want to read a &lt;code&gt;config.json&lt;/code&gt; file, parse it, then read a second file based on a value inside the first.&lt;/p&gt;

&lt;h4&gt;
  
  
  Synchronous Version (Blocking – Don’t do this in production)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;config.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works for small scripts, but in a server handling thousands of requests, it would be disastrous.&lt;/p&gt;

&lt;h4&gt;
  
  
  Asynchronous Version with Callbacks
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;config.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&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;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;configData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error reading config:&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="k"&gt;return&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;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;configData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&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;err&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error reading data file:&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="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Data:&lt;/span&gt;&lt;span class="dl"&gt;'&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="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;Step-by-step callback flow&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;fs.readFile()&lt;/code&gt; is called.&lt;/li&gt;
&lt;li&gt;Node.js delegates the file read to the OS/thread pool.&lt;/li&gt;
&lt;li&gt;The main thread continues executing other code.&lt;/li&gt;
&lt;li&gt;When the OS finishes reading the file, it triggers an event.&lt;/li&gt;
&lt;li&gt;The callback you provided is executed with either an &lt;code&gt;err&lt;/code&gt; or the file content.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This pattern is called &lt;strong&gt;continuation-passing style&lt;/strong&gt;—you pass a function that “continues” the program once the async operation finishes.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Problems with Nested Callbacks (“Callback Hell”)
&lt;/h3&gt;

&lt;p&gt;What happens when you have multiple dependent async operations?&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="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;config.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&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;err1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;configData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err1&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;console&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="nx"&gt;err1&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;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;configData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&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;err2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err2&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;console&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="nx"&gt;err2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&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;err3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err3&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;console&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="nx"&gt;err3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;// Process everything...&lt;/span&gt;
      &lt;span class="nf"&gt;processData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data2&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;This is the infamous &lt;strong&gt;Callback Hell&lt;/strong&gt; or &lt;strong&gt;Pyramid of Doom&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common problems&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deep nesting makes code hard to read and reason about.&lt;/li&gt;
&lt;li&gt;Error handling is repetitive and error-prone.&lt;/li&gt;
&lt;li&gt;Variable scoping becomes messy.&lt;/li&gt;
&lt;li&gt;Difficult to refactor or add new steps.&lt;/li&gt;
&lt;li&gt;Control flow (loops, conditionals) with async operations is painful.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  4. Promise-based Async Handling
&lt;/h3&gt;

&lt;p&gt;Promises represent a value that may be available now, in the future, or never. They provide a cleaner way to handle asynchronous operations.&lt;/p&gt;

&lt;h4&gt;
  
  
  Converting the Example to Promises
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;promises&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Modern way&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;configData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;config.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;configData&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;data1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&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;processData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data2&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;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;loadData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or without &lt;code&gt;async/await&lt;/code&gt; (using &lt;code&gt;.then()&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;config.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&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;configData&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;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;configData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&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;data1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data2&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;data1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data2&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="nf"&gt;processData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data2&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;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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Promise Lifecycle&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pending&lt;/strong&gt;: Initial state, neither fulfilled nor rejected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fulfilled&lt;/strong&gt;: Operation completed successfully (&lt;code&gt;resolve()&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rejected&lt;/strong&gt;: Operation failed (&lt;code&gt;reject()&lt;/code&gt; or unhandled error).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can chain &lt;code&gt;.then()&lt;/code&gt; for success and &lt;code&gt;.catch()&lt;/code&gt; for errors. Promises also support &lt;code&gt;.finally()&lt;/code&gt; for cleanup.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. Benefits of Promises
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Callbacks&lt;/th&gt;
&lt;th&gt;Promises&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Readability&lt;/td&gt;
&lt;td&gt;Poor (nested)&lt;/td&gt;
&lt;td&gt;Excellent (chaining + async/await)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Error Handling&lt;/td&gt;
&lt;td&gt;Repetitive, manual&lt;/td&gt;
&lt;td&gt;Centralized with &lt;code&gt;.catch()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parallel Operations&lt;/td&gt;
&lt;td&gt;Very difficult&lt;/td&gt;
&lt;td&gt;Easy with &lt;code&gt;Promise.all()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Control Flow&lt;/td&gt;
&lt;td&gt;Hard (loops, conditions)&lt;/td&gt;
&lt;td&gt;Natural with async/await&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Debugging&lt;/td&gt;
&lt;td&gt;Stack traces are messy&lt;/td&gt;
&lt;td&gt;Much better stack traces&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintainability&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Modern best practice&lt;/strong&gt;: Use &lt;code&gt;async/await&lt;/code&gt; (which is syntactic sugar over Promises) for most code. It makes asynchronous code look and behave almost like synchronous code while retaining all the non-blocking benefits.&lt;/p&gt;




&lt;h3&gt;
  
  
  Visualizing the Concepts
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Callback Execution Chain&lt;/strong&gt; (Conceptual Diagram):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Main Thread
   ↓
fs.readFile() → delegates to libuv
   ↓ (non-blocking)
Continue other work
   ↓ (when OS finishes)
Callback 1 fires → fs.readFile() inside callback
   ↓
Callback 2 fires → and so on...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Promise Lifecycle Flow&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Pending 
  ├──► Fulfilled → .then() handlers
  └──► Rejected  → .catch() handler
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Final Tips for Modern Node.js Development
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Always prefer the &lt;code&gt;fs.promises&lt;/code&gt; API or libraries that return Promises.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;async/await&lt;/code&gt; + &lt;code&gt;try/catch&lt;/code&gt; for most business logic.&lt;/li&gt;
&lt;li&gt;Handle errors at the right level—don’t let unhandled promise rejections crash your app (use process-level handlers in older code).&lt;/li&gt;
&lt;li&gt;For complex flows, consider libraries like &lt;code&gt;p-limit&lt;/code&gt;, &lt;code&gt;async&lt;/code&gt;, or just stick with native &lt;code&gt;Promise.allSettled()&lt;/code&gt; when needed.&lt;/li&gt;
&lt;li&gt;Understand that &lt;code&gt;async/await&lt;/code&gt; is still asynchronous under the hood—don’t block the event loop with heavy CPU work.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Callbacks were the foundation of Node.js asynchronous programming and taught us valuable lessons about non-blocking I/O. However, Promises (and especially &lt;code&gt;async/await&lt;/code&gt;) dramatically improved developer experience while preserving performance.&lt;/p&gt;

&lt;p&gt;Mastering both gives you deep insight into how Node.js works and allows you to read and maintain codebases of any age.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What’s next?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Explore &lt;code&gt;async iterators&lt;/code&gt;, &lt;code&gt;EventEmitter&lt;/code&gt;, or move on to streams—the next level of powerful asynchronous patterns in Node.js.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Happy coding! If you enjoyed this post, share it with your fellow developers or leave a comment with your biggest async challenge.&lt;/em&gt; &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>chaicode</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How React Virtual DOM works under the Hood</title>
      <dc:creator>Bhupesh Chandra Joshi</dc:creator>
      <pubDate>Tue, 05 May 2026 16:35:53 +0000</pubDate>
      <link>https://forem.com/bhupeshchandrajoshi/how-react-virtual-dom-works-under-the-hood-4b2l</link>
      <guid>https://forem.com/bhupeshchandrajoshi/how-react-virtual-dom-works-under-the-hood-4b2l</guid>
      <description>&lt;p&gt;&lt;strong&gt;What problem the Virtual DOM solves?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Consider this scenario there are two couple in house. The girlfriend is the real dom , when couple has Chit-chat and when girlfriend experiences the intense anger and she rearranges the complete home , Back in the day the old-school/collage days before May 29, 2013(without Virtual DOM). The girl says shift the bed shift + furniture shift + curtains change + lighting change. You need to repaint the whole room. After 5 min she said to you , keep them right.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;After the complete demolition of the structure of home, you reset all the home settings. Result you understood the problem - time waste and your girlfriend is still angry.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Virtual DOM, on a path of self-improvement just rearranges the structure , after creating the mini model virtual dom on your mind. You shift the table ,&lt;br&gt;
The rest of the setup is identical, except for the repositioned table. You don't touched your home, it's not joke , it is the real problem virtual dom solves.&lt;br&gt;
So, it blocks the unnecessary DOM manipulations.&lt;br&gt;
In browser unnessary DOM manipulation is slow and costly. The real dom leverages the diffing algorithm similar algorith github utilizes on their commit ,where it represents the paint by +++++=&amp;gt; addition and ------=&amp;gt; deletion of code. Browser updates the content with diffing algorithm, it changes only required , it doesn't touch unnessary jsx elements on web browser.&lt;/p&gt;

&lt;p&gt;SO , YOU SHOULD REMEMBER TRIGGER, WHEN girlfriend becomes angry ,don't break whole house, instead of this, create a model and change the necessary.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft622muph8vl0pfwx81ud.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft622muph8vl0pfwx81ud.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🚀 Real DOM vs Virtual DOM: The Epic Battle Explained with Real-Life Stories!&lt;/strong&gt; 🔥&lt;/p&gt;

&lt;p&gt;AKA Difference between Real DOM vs Virtual DOM&lt;/p&gt;

&lt;p&gt;Hey friend!  Grab your favorite drink, sit comfortably, and let's dive in! 💪&lt;/p&gt;

&lt;h3&gt;
  
  
  Imagine You're Running a Super Busy Restaurant 🍽️
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Real DOM = Your Physical Restaurant (Slow &amp;amp; Expensive)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every single order (change) forces you to &lt;strong&gt;shut down the entire restaurant&lt;/strong&gt;, rearrange tables, repaint walls, move furniture, and rebuild the kitchen — even if only one table ordered extra fries!&lt;/li&gt;
&lt;li&gt;Tiny update? Whole place gets disrupted → customers (users) get angry, everything slows down, lights flicker, music stops. &lt;/li&gt;
&lt;li&gt;This is &lt;strong&gt;exactly&lt;/strong&gt; how the &lt;strong&gt;Real DOM&lt;/strong&gt; works in the browser. 

&lt;ul&gt;
&lt;li&gt;It's the actual living HTML page.&lt;/li&gt;
&lt;li&gt;Change one thing (like updating a like counter) → browser recalculates &lt;strong&gt;everything&lt;/strong&gt; (layout, styles, positions). &lt;/li&gt;
&lt;li&gt;Result? Slow performance, laggy apps, high battery drain. 😩&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Virtual DOM = Your Smart Digital Ordering App (Fast &amp;amp; Genius)&lt;/strong&gt; ⚡&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have a &lt;strong&gt;digital twin&lt;/strong&gt; of your restaurant on a super-fast tablet.&lt;/li&gt;
&lt;li&gt;Customer wants extra fries? You quickly edit it on the &lt;strong&gt;tablet&lt;/strong&gt; (Virtual DOM).&lt;/li&gt;
&lt;li&gt;The app &lt;strong&gt;compares&lt;/strong&gt; (Diffing) the new order with the old one and says: &lt;em&gt;"Only Table 7 needs fries — just tell the chef that!"&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Only that one small change happens in the real restaurant. No shutting down, no chaos, no angry customers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is &lt;strong&gt;Virtual DOM&lt;/strong&gt; (used by React, Vue, etc.):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lightweight JavaScript copy of the Real DOM.&lt;/li&gt;
&lt;li&gt;You make changes here freely and fast.&lt;/li&gt;
&lt;li&gt;It calculates the &lt;strong&gt;minimum changes&lt;/strong&gt; needed.&lt;/li&gt;
&lt;li&gt;Then it &lt;strong&gt;batches&lt;/strong&gt; them and updates only what's necessary in the Real DOM.&lt;/li&gt;
&lt;li&gt;Result? Blazing fast, smooth apps like Facebook, Netflix, or Instagram feel buttery smooth.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  More Memorable Real-Life Examples 🧠
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concept&lt;/th&gt;
&lt;th&gt;Real Life Example&lt;/th&gt;
&lt;th&gt;Why It Sticks&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Real DOM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Writing an exam on paper. One mistake? Tear the whole page &amp;amp; rewrite everything.&lt;/td&gt;
&lt;td&gt;Painful &amp;amp; slow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Virtual DOM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Writing on a whiteboard or Google Doc. Edit, erase, compare, then only finalize final version.&lt;/td&gt;
&lt;td&gt;Quick &amp;amp; efficient&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Real DOM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Rebuilding an entire Lego city for one missing brick.&lt;/td&gt;
&lt;td&gt;Overkill&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Virtual DOM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Keeping a photo of your Lego city, editing the photo first, then only replacing that one brick.&lt;/td&gt;
&lt;td&gt;Smart!&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  The Magic Trick: Diffing + Reconciliation ✨
&lt;/h3&gt;

&lt;p&gt;Virtual DOM doesn't just copy — it &lt;strong&gt;smartly diffs&lt;/strong&gt; (compares) trees like a detective:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creates new Virtual DOM tree after your update.&lt;/li&gt;
&lt;li&gt;Compares with previous one.&lt;/li&gt;
&lt;li&gt;Finds differences.&lt;/li&gt;
&lt;li&gt;Applies &lt;strong&gt;only&lt;/strong&gt; those differences to Real DOM.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;strong&gt;1. Initial Render Process in React&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;initial render&lt;/strong&gt; (also called mounting) is the first time React builds the UI for your component tree.&lt;/p&gt;

&lt;p&gt;Here's what happens step by step:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;ReactDOM.render() / createRoot.render()&lt;/strong&gt; is called with your root component (e.g., &lt;code&gt;&amp;lt;App /&amp;gt;&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;React calls your component function (or &lt;code&gt;render()&lt;/code&gt; in class components). This is the "render phase".&lt;/li&gt;
&lt;li&gt;During this execution:

&lt;ul&gt;
&lt;li&gt;All hooks run in order (&lt;code&gt;useState&lt;/code&gt;, &lt;code&gt;useEffect&lt;/code&gt;, &lt;code&gt;useMemo&lt;/code&gt;, etc.).&lt;/li&gt;
&lt;li&gt;JSX is converted into React elements (plain JS objects describing what the UI should look like).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;React builds the &lt;strong&gt;Virtual DOM&lt;/strong&gt; — a lightweight in-memory representation of the real DOM.&lt;/li&gt;
&lt;li&gt;React compares the new Virtual DOM with an empty previous tree (nothing exists yet) and figures out what needs to be created.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commit phase&lt;/strong&gt;: React makes the actual DOM mutations (creates nodes, sets attributes, adds event listeners).&lt;/li&gt;
&lt;li&gt;After the DOM is updated, &lt;code&gt;useLayoutEffect&lt;/code&gt; runs (synchronously), then &lt;code&gt;useEffect&lt;/code&gt; (asynchronously).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is why your first &lt;code&gt;console.log&lt;/code&gt; in a component happens before you see anything on screen — rendering and committing are separate.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;2. How State or Props Changes Trigger Re-render&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;React follows a &lt;strong&gt;"render on data change"&lt;/strong&gt; model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Triggers for re-render:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;State change&lt;/strong&gt; (&lt;code&gt;setState&lt;/code&gt;, &lt;code&gt;useState&lt;/code&gt; setter, Redux dispatch, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Props change&lt;/strong&gt; (parent re-rendered and passed new props)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context value change&lt;/strong&gt; (if component consumes that context)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parent re-render&lt;/strong&gt; (children re-render by default unless memoized)&lt;/li&gt;
&lt;li&gt;Hooks like &lt;code&gt;useReducer&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What actually happens during re-render:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A state/prop update is scheduled.&lt;/li&gt;
&lt;li&gt;React starts the &lt;strong&gt;reconciliation&lt;/strong&gt; (diffing) process from the component that changed (and its subtree).&lt;/li&gt;
&lt;li&gt;The component function runs &lt;strong&gt;again&lt;/strong&gt; from top to bottom.&lt;/li&gt;
&lt;li&gt;New Virtual DOM is created for that subtree.&lt;/li&gt;
&lt;li&gt;React &lt;strong&gt;diffs&lt;/strong&gt; the new Virtual DOM with the previous one (fiber tree).&lt;/li&gt;
&lt;li&gt;Only the parts that actually changed are updated in the real DOM (thanks to the heuristic algorithm).&lt;/li&gt;
&lt;li&gt;Commit phase again → effects.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Important optimizations:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;React.memo()&lt;/code&gt; on functional components&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useMemo&lt;/code&gt;, &lt;code&gt;useCallback&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;React.PureComponent&lt;/code&gt; / &lt;code&gt;shouldComponentUpdate&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Moving state down / lifting state up wisely&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pro tip&lt;/strong&gt;: Not every state update causes a visible DOM change. React batches updates in event handlers for performance.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr0oh6va869ahxwp4fr9m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr0oh6va869ahxwp4fr9m.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>webdev</category>
      <category>chaicode</category>
    </item>
    <item>
      <title>React Native CLI Installation Guide: Step-by-Step for (Windows, macOS &amp; Linux)</title>
      <dc:creator>Bhupesh Chandra Joshi</dc:creator>
      <pubDate>Thu, 23 Apr 2026 14:44:04 +0000</pubDate>
      <link>https://forem.com/bhupeshchandrajoshi/react-native-cli-installation-guide-step-by-step-for-windows-macos-linux-4lb</link>
      <guid>https://forem.com/bhupeshchandrajoshi/react-native-cli-installation-guide-step-by-step-for-windows-macos-linux-4lb</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;React Native continues to be one of the most popular frameworks for building cross-platform mobile apps using JavaScript and React. While Expo is great for quick prototyping, &lt;strong&gt;React Native CLI&lt;/strong&gt; gives you full control, better performance, and easier access to native modules.&lt;/p&gt;

&lt;p&gt;In this comprehensive guide, I'll walk you through the complete &lt;strong&gt;React Native CLI installation&lt;/strong&gt; process for &lt;strong&gt;Windows&lt;/strong&gt;, &lt;strong&gt;macOS&lt;/strong&gt;, and &lt;strong&gt;Linux&lt;/strong&gt; in 2026.&lt;/p&gt;




&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Before starting, make sure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A decent computer (at least 8GB RAM recommended, 16GB+ for smooth development)&lt;/li&gt;
&lt;li&gt;Stable internet connection&lt;/li&gt;
&lt;li&gt;Administrative access on your machine&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  1. Install Node.js and npm
&lt;/h3&gt;

&lt;p&gt;React Native requires &lt;strong&gt;Node.js 18 or higher&lt;/strong&gt; (LTS version recommended).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recommended way (2026):&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Using Official Installer (Easiest)
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Go to the official Node.js website: &lt;a href="https://nodejs.org" rel="noopener noreferrer"&gt;https://nodejs.org&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Download the &lt;strong&gt;LTS&lt;/strong&gt; version (currently 20.x or 22.x)&lt;/li&gt;
&lt;li&gt;Install it with default settings&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Verify Installation
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;--version&lt;/span&gt;
npm &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see versions like &lt;code&gt;v20.x.x&lt;/code&gt; or &lt;code&gt;v22.x.x&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro Tip:&lt;/strong&gt; Use &lt;strong&gt;nvm&lt;/strong&gt; (Node Version Manager) for better version management.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Install Watchman (macOS &amp;amp; Linux only)
&lt;/h3&gt;

&lt;p&gt;Watchman improves file watching performance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# macOS (using Homebrew)&lt;/span&gt;
brew &lt;span class="nb"&gt;install &lt;/span&gt;watchman

&lt;span class="c"&gt;# Linux&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;watchman   &lt;span class="c"&gt;# Ubuntu/Debian&lt;/span&gt;
&lt;span class="c"&gt;# or use your distro's package manager&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  3. Install React Native CLI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; react-native-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; In newer versions, you usually don't need to install &lt;code&gt;react-native-cli&lt;/code&gt; globally anymore. You can directly use &lt;code&gt;npx react-native&lt;/code&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. Platform-Specific Setup
&lt;/h3&gt;

&lt;h4&gt;
  
  
  For Android (All Operating Systems)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Install Android Studio&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download Android Studio from &lt;a href="https://developer.android.com/studio" rel="noopener noreferrer"&gt;https://developer.android.com/studio&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Install it with these components:

&lt;ul&gt;
&lt;li&gt;Android SDK&lt;/li&gt;
&lt;li&gt;Android SDK Platform-Tools&lt;/li&gt;
&lt;li&gt;Android SDK Build-Tools&lt;/li&gt;
&lt;li&gt;Android Emulator&lt;/li&gt;
&lt;li&gt;Android Virtual Device (AVD)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Set Environment Variables&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;Add these to System Environment Variables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ANDROID_HOME&lt;/code&gt; = &lt;code&gt;C:\Users\YourName\AppData\Local\Android\Sdk&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add to PATH:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;%ANDROID_HOME%\platform-tools&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%ANDROID_HOME%\emulator&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%ANDROID_HOME%\tools&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%ANDROID_HOME%\tools\bin&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;macOS &amp;amp; Linux:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Add to &lt;code&gt;~/.zshrc&lt;/code&gt; or &lt;code&gt;~/.bash_profile&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANDROID_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;/Library/Android/sdk   &lt;span class="c"&gt;# macOS&lt;/span&gt;
&lt;span class="c"&gt;# export ANDROID_HOME=$HOME/Android/Sdk       # Linux&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;:&lt;span class="nv"&gt;$ANDROID_HOME&lt;/span&gt;/emulator
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;:&lt;span class="nv"&gt;$ANDROID_HOME&lt;/span&gt;/platform-tools
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;:&lt;span class="nv"&gt;$ANDROID_HOME&lt;/span&gt;/tools
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;:&lt;span class="nv"&gt;$ANDROID_HOME&lt;/span&gt;/tools/bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3: Install Platform Tools &amp;amp; SDK&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open Android Studio → SDK Manager → Install:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SDK Platforms: Android 15 (VanillaIceCream) or Android 14&lt;/li&gt;
&lt;li&gt;SDK Tools: Android SDK Build-Tools, Platform-Tools, Emulator&lt;/li&gt;
&lt;/ul&gt;




&lt;h4&gt;
  
  
  For iOS (macOS only)
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Install &lt;strong&gt;Xcode&lt;/strong&gt; from Mac App Store (Xcode 16+ recommended)&lt;/li&gt;
&lt;li&gt;Install Command Line Tools:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;xcode-select &lt;span class="nt"&gt;--install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Install CocoaPods (for native dependencies):
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;gem &lt;span class="nb"&gt;install &lt;/span&gt;cocoapods
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or using Homebrew (recommended):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;cocoapods
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  5. Create Your First React Native App
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx react-native init MyAwesomeApp
&lt;span class="nb"&gt;cd &lt;/span&gt;MyAwesomeApp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  6. Run the App
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Android:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx react-native run-android
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;iOS (macOS only):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx react-native run-ios
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Common Issues &amp;amp; Troubleshooting (2026)
&lt;/h3&gt;

&lt;p&gt;Here are the most common problems developers face:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;"SDK location not found"&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
→ Make sure &lt;code&gt;ANDROID_HOME&lt;/code&gt; is correctly set.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Gradle sync failed / Build failed&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
→ Run &lt;code&gt;./gradlew clean&lt;/code&gt; in &lt;code&gt;android&lt;/code&gt; folder.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Metro bundler not starting&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
→ Kill all Node processes and try again.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CocoaPods issues on macOS&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
→ Run &lt;code&gt;pod install --repo-update&lt;/code&gt; in &lt;code&gt;ios&lt;/code&gt; folder.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Java version mismatch&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
→ React Native 0.76+ recommends &lt;strong&gt;JDK 21&lt;/strong&gt; or &lt;strong&gt;JDK 17&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Quick Fix for Java:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check Java version&lt;/span&gt;
java &lt;span class="nt"&gt;-version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Bonus: Recommended Development Setup (2026)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Editor&lt;/strong&gt;: VS Code + React Native Tools extension&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Package Manager&lt;/strong&gt;: Yarn or pnpm (faster than npm)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State Management&lt;/strong&gt;: Zustand or Redux Toolkit&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Navigation&lt;/strong&gt;: React Navigation 7&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing&lt;/strong&gt;: Jest + React Native Testing Library&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Congratulations! 🎉 You have successfully installed &lt;strong&gt;React Native CLI&lt;/strong&gt; on your machine.&lt;/p&gt;

&lt;p&gt;You’re now ready to build powerful cross-platform mobile applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Next Steps:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learn React Navigation&lt;/li&gt;
&lt;li&gt;Explore Native Modules&lt;/li&gt;
&lt;li&gt;Set up CI/CD with GitHub Actions&lt;/li&gt;
&lt;li&gt;Publish your first app to Play Store &amp;amp; App Store&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Would you like me to add:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A section on using Yarn instead of npm?&lt;/li&gt;
&lt;li&gt;M1/M2/M3/M4 Mac specific instructions?&lt;/li&gt;
&lt;li&gt;React Native 0.76+ new architecture (Fabric + TurboModules)?&lt;/li&gt;
&lt;li&gt;Docker setup for React Native?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let me know in the comments!&lt;/p&gt;




&lt;h3&gt;
  
  
  Tags for Hashnode:
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;react-native&lt;/code&gt;, &lt;code&gt;reactnative&lt;/code&gt;, &lt;code&gt;mobile-development&lt;/code&gt;, &lt;code&gt;javascript&lt;/code&gt;, &lt;code&gt;tutorial&lt;/code&gt;, &lt;code&gt;cli&lt;/code&gt;, &lt;code&gt;android&lt;/code&gt;, &lt;code&gt;ios&lt;/code&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Meta Image Suggestion:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Create a clean thumbnail with React Native logo + terminal screenshot + "Installation Guide 2026"&lt;/p&gt;




&lt;p&gt;This blog is fully updated for 2026, beginner-friendly, and SEO-optimized for Hashnode.&lt;/p&gt;

&lt;p&gt;Would you like me to make a &lt;strong&gt;shorter version&lt;/strong&gt;, &lt;strong&gt;more advanced version&lt;/strong&gt;, or add &lt;strong&gt;code screenshots&lt;/strong&gt; sections? Just tell me!&lt;/p&gt;

</description>
      <category>chaicode</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>reactnative</category>
    </item>
    <item>
      <title>Beyond the Cover: Demystifying JavaScript's this Keyword</title>
      <dc:creator>Bhupesh Chandra Joshi</dc:creator>
      <pubDate>Thu, 23 Apr 2026 04:05:11 +0000</pubDate>
      <link>https://forem.com/bhupeshchandrajoshi/beyond-the-cover-demystifying-javascripts-this-keyword-494a</link>
      <guid>https://forem.com/bhupeshchandrajoshi/beyond-the-cover-demystifying-javascripts-this-keyword-494a</guid>
      <description>&lt;p&gt;The &lt;code&gt;this&lt;/code&gt; keyword is often treated like a final boss in JavaScript, but it’s actually more like a &lt;strong&gt;dynamic pointer&lt;/strong&gt; that changes depending on who is "talking" at the moment. &lt;/p&gt;

&lt;p&gt;Think of &lt;code&gt;this&lt;/code&gt; as a pronoun. In English, if I say "I am reading," the word "I" refers to me. If you say it, "I" refers to you. In JavaScript, &lt;code&gt;this&lt;/code&gt; refers to the &lt;strong&gt;object that is currently executing the code&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. What &lt;code&gt;this&lt;/code&gt; Represents
&lt;/h2&gt;

&lt;p&gt;At its core, &lt;code&gt;this&lt;/code&gt; is a reference to an object. It doesn't have a fixed value; its value is determined &lt;strong&gt;at the moment a function is called&lt;/strong&gt;, not when it is written. &lt;/p&gt;




&lt;h2&gt;
  
  
  2. &lt;code&gt;this&lt;/code&gt; in the Global Context
&lt;/h2&gt;

&lt;p&gt;When you use &lt;code&gt;this&lt;/code&gt; outside of any function or object, it defaults to the "Global Object." &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In a &lt;strong&gt;web browser&lt;/strong&gt;, the global object is &lt;code&gt;window&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If you type &lt;code&gt;console.log(this);&lt;/code&gt; in your browser console, it will return the &lt;code&gt;Window&lt;/code&gt; object.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you are using "strict mode" (&lt;code&gt;'use strict';&lt;/code&gt;), &lt;code&gt;this&lt;/code&gt; in a global function will be &lt;code&gt;undefined&lt;/code&gt; instead of the window, which helps prevent accidental changes to global variables.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  3. &lt;code&gt;this&lt;/code&gt; Inside Objects (The "Method" Context)
&lt;/h2&gt;

&lt;p&gt;When a function is part of an object, we call it a &lt;strong&gt;method&lt;/strong&gt;. In this case, &lt;code&gt;this&lt;/code&gt; refers to the object that "owns" the method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bhupesh&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;book&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Eloquent JavaScript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Hi, I'm &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; and I'm reading &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// "this" refers to the reader object&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, &lt;code&gt;this.name&lt;/code&gt; is the same as saying &lt;code&gt;reader.name&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. &lt;code&gt;this&lt;/code&gt; Inside Regular Functions
&lt;/h2&gt;

&lt;p&gt;This is where it gets tricky. If you call a regular function that isn't a method of an object, &lt;code&gt;this&lt;/code&gt; still points to the global object (or &lt;code&gt;undefined&lt;/code&gt; in strict mode).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;showContext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;showContext&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Logs the Window object&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5. How Calling Context Changes Everything
&lt;/h2&gt;

&lt;p&gt;The golden rule to remember is: &lt;strong&gt;&lt;code&gt;this&lt;/code&gt; is determined by how the function is called.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine a function as a tool. The tool doesn't care who owns it until someone picks it up to use it. The person who picks it up is the &lt;strong&gt;caller&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common Scenarios:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simple Call:&lt;/strong&gt; &lt;code&gt;myFunction()&lt;/code&gt; → &lt;code&gt;this&lt;/code&gt; is the Global Object.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Method Call:&lt;/strong&gt; &lt;code&gt;myObject.myMethod()&lt;/code&gt; → &lt;code&gt;this&lt;/code&gt; is &lt;code&gt;myObject&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Arrow Functions:&lt;/strong&gt; These are special! They don't have their own &lt;code&gt;this&lt;/code&gt;. They "borrow" it from the code surrounding them. This is why they are so popular in modern frameworks—they keep the context predictable.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Summary Table
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Context&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;this&lt;/code&gt; refers to...&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Global&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Window (browser) or Global (Node.js)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Object Method&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The object itself&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Arrow Function&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The context where it was created&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Event Listener&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The element that received the event&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;By focusing on the &lt;strong&gt;caller&lt;/strong&gt; of the function rather than where the function is defined, you'll find that &lt;code&gt;this&lt;/code&gt; becomes much easier to track. Happy coding!&lt;/p&gt;

</description>
      <category>chaicode</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Mastering Map and Set in JavaScript: Beyond Objects and Arrays</title>
      <dc:creator>Bhupesh Chandra Joshi</dc:creator>
      <pubDate>Thu, 23 Apr 2026 03:04:52 +0000</pubDate>
      <link>https://forem.com/bhupeshchandrajoshi/mastering-map-and-set-in-javascript-beyond-objects-and-arrays-450f</link>
      <guid>https://forem.com/bhupeshchandrajoshi/mastering-map-and-set-in-javascript-beyond-objects-and-arrays-450f</guid>
      <description>

&lt;p&gt;If you’ve been writing JavaScript for a while, you’re likely intimately familiar with &lt;strong&gt;Objects&lt;/strong&gt; and &lt;strong&gt;Arrays&lt;/strong&gt;. They are the bread and butter of data structures in JS. We use Objects to store key-value pairs and Arrays to store ordered lists. &lt;/p&gt;

&lt;p&gt;But as your applications grow in complexity, you might start hitting the inherent limitations of these traditional structures. Enter &lt;strong&gt;Map&lt;/strong&gt; and &lt;strong&gt;Set&lt;/strong&gt;—introduced in ES6 to solve the exact edge cases and performance bottlenecks that Objects and Arrays struggle with.&lt;/p&gt;

&lt;p&gt;Let's dive into what they are, how they differ from the classics, and when you should reach for them.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛑 The Problem with Traditional Objects and Arrays
&lt;/h2&gt;

&lt;p&gt;Before we look at the solutions, let's understand the problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Limitations of &lt;code&gt;Object&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Objects are fantastic, but they were never designed to be pure dictionaries. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Key Types are Restricted:&lt;/strong&gt; Object keys &lt;em&gt;must&lt;/em&gt; be Strings or Symbols. If you try to use a Number or another Object as a key, JavaScript will silently coerce it into a string (e.g., &lt;code&gt;"[object Object]"&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accidental Collisions:&lt;/strong&gt; Objects inherit from &lt;code&gt;Object.prototype&lt;/code&gt;. This means keys like &lt;code&gt;toString&lt;/code&gt; or &lt;code&gt;constructor&lt;/code&gt; already exist and can cause weird bugs if you accidentally overwrite them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Native Size Property:&lt;/strong&gt; Finding out how many items are in an object requires &lt;code&gt;Object.keys(obj).length&lt;/code&gt;, which is an $O(N)$ operation.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Limitations of &lt;code&gt;Array&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Arrays are great for ordered lists, but they struggle with uniqueness and fast lookups.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Duplicates:&lt;/strong&gt; Arrays allow duplicate values. If you want a list of &lt;em&gt;unique&lt;/em&gt; items, you have to manually write logic to filter them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slow Lookups:&lt;/strong&gt; Checking if an array contains an item using &lt;code&gt;array.includes()&lt;/code&gt; or finding an item with &lt;code&gt;array.indexOf()&lt;/code&gt; forces JavaScript to scan the array one by one—an $O(N)$ operation.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🗺️ What is a &lt;code&gt;Map&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;A &lt;code&gt;Map&lt;/code&gt; is a collection of keyed data items, just like an Object. However, the killer feature of a Map is that it allows &lt;strong&gt;keys of any type&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Functions, Objects, primitive types (like Numbers and Booleans)—literally anything can be used as a key in a Map.&lt;/p&gt;

&lt;h3&gt;
  
  
  Map Key-Value Storage Visual
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+------------------------+       +-------------------------+
|          KEY           |       |          VALUE          |
+------------------------+       +-------------------------+
| "standardString"       | ----&amp;gt; | "Hello World"           |
| 42                     | ----&amp;gt; | "A number key!"         |
| { user: "john_doe" }   | ----&amp;gt; | { sessionToken: "xyz" } |
| document.body          | ----&amp;gt; | "DOM Node attached!"    |
+------------------------+       +-------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Map in Action
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userRoles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&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;userObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Using an object as a key!&lt;/span&gt;
&lt;span class="nx"&gt;userRoles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userObj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userRoles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userObj&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Output: 'Admin'&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="nx"&gt;userRoles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;         &lt;span class="c1"&gt;// Output: 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Map vs. Object
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;&lt;code&gt;Map&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;Object&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Key Types&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Any type (Objects, Functions, Primitives)&lt;/td&gt;
&lt;td&gt;Strings and Symbols only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Size&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Easily accessed via &lt;code&gt;map.size&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Must manually calculate &lt;code&gt;Object.keys(obj).length&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Iteration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Directly iterable (using &lt;code&gt;for...of&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Requires &lt;code&gt;Object.keys()&lt;/code&gt;, &lt;code&gt;values()&lt;/code&gt;, or &lt;code&gt;entries()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Order&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Guaranteed strictly by insertion order&lt;/td&gt;
&lt;td&gt;Not fully guaranteed (complex historical rules)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Performance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Optimized for frequent additions/removals&lt;/td&gt;
&lt;td&gt;Slower for frequent dynamic key additions/removals&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🛡️ What is a &lt;code&gt;Set&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;A &lt;code&gt;Set&lt;/code&gt; is a collection of values where each value must be &lt;strong&gt;strictly unique&lt;/strong&gt;. You can think of it as an Array that automatically filters out duplicates. &lt;/p&gt;

&lt;h3&gt;
  
  
  Set Uniqueness Representation
&lt;/h3&gt;

&lt;p&gt;When you feed data into a Set, it acts as an automatic filter, rejecting any value it already holds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input Stream: [ 1, 5, "hello", 1, 5, 8 ]

     +-----------------------------------+
     |            SET FILTER             |
---&amp;gt; |  (Analyzes incoming values.       | ---&amp;gt; Result: { 1, 5, "hello", 8 }
     |   Drops the second '1'            |
     |   Drops the second '5')           |
     +-----------------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set in Action
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;uniqueTags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;uniqueTags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;javascript&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;uniqueTags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;uniqueTags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;javascript&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Ignored! Already exists.&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="nx"&gt;uniqueTags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Output: 2&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="nx"&gt;uniqueTags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Output: true (O(1) lookup!)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set vs. Array
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;&lt;code&gt;Set&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;Array&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Uniqueness&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Guaranteed unique values only&lt;/td&gt;
&lt;td&gt;Allows duplicate values&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Lookup Performance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$O(1)$ fast lookups using &lt;code&gt;set.has(value)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;$O(N)$ slow lookups using &lt;code&gt;array.includes(value)&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Access&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No index-based access&lt;/td&gt;
&lt;td&gt;Accessed via index (e.g., &lt;code&gt;arr[0]&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best For&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Checking if an item exists, removing duplicates&lt;/td&gt;
&lt;td&gt;Maintaining a specific ordered sequence of items&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🛠️ When to Use Map and Set
&lt;/h2&gt;

&lt;p&gt;Knowing &lt;em&gt;how&lt;/em&gt; they work is only half the battle. Here are the practical rules of thumb for when to pull them out in your daily coding.&lt;/p&gt;

&lt;h3&gt;
  
  
  When to use &lt;code&gt;Map&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;When keys are unknown until runtime:&lt;/strong&gt; If you are building a dictionary dynamically based on user input, a &lt;code&gt;Map&lt;/code&gt; is safer because it won't collide with prototype keys.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When you need to associate data with a DOM node or Object:&lt;/strong&gt; If you want to attach state to a DOM element without modifying the element itself, use the DOM element as a key in a &lt;code&gt;Map&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When you are constantly adding and removing key-value pairs:&lt;/strong&gt; &lt;code&gt;Map&lt;/code&gt; is heavily optimized in V8 (the JavaScript engine) for frequent mutations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  When to use &lt;code&gt;Set&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;When you need to deduplicate an Array:&lt;/strong&gt; This is the most common use case. You can instantly strip duplicates from an array using &lt;code&gt;const unique = [...new Set(myArray)]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When you need to perform quick lookups:&lt;/strong&gt; If you have a massive list of blocked IDs, and you need to check if a user is blocked on every request, &lt;code&gt;Set.has(id)&lt;/code&gt; is astronomically faster than &lt;code&gt;Array.includes(id)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When tracking relationships or statuses:&lt;/strong&gt; Storing a list of "currently active users" or "items currently selected" in a UI. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Objects and Arrays aren't going anywhere; they are still the fundamental building blocks of JavaScript. However, &lt;code&gt;Map&lt;/code&gt; and &lt;code&gt;Set&lt;/code&gt; provide specialized, highly optimized tools for specific scenarios. By understanding their strengths, you can write cleaner, safer, and much faster code.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>chaicode</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Understanding JavaScript Promises: A Comprehensive Guide</title>
      <dc:creator>Bhupesh Chandra Joshi</dc:creator>
      <pubDate>Thu, 23 Apr 2026 02:59:46 +0000</pubDate>
      <link>https://forem.com/bhupeshchandrajoshi/understanding-javascript-promises-a-comprehensive-guide-5186</link>
      <guid>https://forem.com/bhupeshchandrajoshi/understanding-javascript-promises-a-comprehensive-guide-5186</guid>
      <description>&lt;p&gt;JavaScript promises are a powerful feature that help manage asynchronous operations in a more readable and manageable way. In this article, we will explore the essential aspects of promises, including their lifecycle, how to handle success and failure, and the advantages they offer over traditional callback methods.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Problems Do Promises Solve?
&lt;/h2&gt;

&lt;p&gt;Promises address several key issues in asynchronous programming:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Callback Hell&lt;/strong&gt;: When multiple callbacks are nested, the code can become difficult to read and maintain. Promises flatten the structure, making it easier to follow the flow of operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Handling&lt;/strong&gt;: With callbacks, error handling can become convoluted. Promises provide a standardized way to handle errors, improving code reliability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chaining Operations&lt;/strong&gt;: Promises allow for chaining multiple asynchronous operations, enabling a more linear and understandable flow of logic.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Promise States
&lt;/h2&gt;

&lt;p&gt;A promise can be in one of three states:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pending&lt;/strong&gt;: The initial state, meaning the promise is still being processed and is neither fulfilled nor rejected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fulfilled&lt;/strong&gt;: The operation completed successfully, and the promise has a resulting value.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rejected&lt;/strong&gt;: The operation failed, and the promise has a reason for the failure (an error).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Basic Promise Lifecycle
&lt;/h2&gt;

&lt;p&gt;Understanding the lifecycle of a promise is crucial for effective usage. Here’s a basic flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Creation&lt;/strong&gt;: A promise is created and starts in the pending state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resolution&lt;/strong&gt;: The promise transitions to either fulfilled or rejected based on the outcome of the asynchronous operation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handling&lt;/strong&gt;: Once resolved, you can handle the result or error using &lt;code&gt;.then()&lt;/code&gt; for success and &lt;code&gt;.catch()&lt;/code&gt; for failure.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Diagram: Promise Lifecycle
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;id: promise-lifecycle-diagram
name: Promise Lifecycle Diagram
type: mermaid
content: |-
  graph TD;
      A[Pending] --&amp;gt;|Fulfilled| B[Resolved]
      A --&amp;gt;|Rejected| C[Error]
      B --&amp;gt; D[Handle Success]
      C --&amp;gt; E[Handle Error]
```

`

## Handling Success and Failure

Promises provide a clear and concise way to handle both success and failure:

- **Success Handling**: Use the `.then()` method to specify what to do when a promise is fulfilled.
- **Failure Handling**: Use the `.catch()` method to specify how to handle errors when a promise is rejected.

### Example Code

```javascript
let myPromise = new Promise((resolve, reject) =&amp;gt; {
    // Simulating an asynchronous operation
    setTimeout(() =&amp;gt; {
        const success = true; // Change to false to simulate failure
        if (success) {
            resolve("Operation succeeded!");
        } else {
            reject("Operation failed!");
        }
    }, 1000);
});

myPromise
    .then(result =&amp;gt; console.log(result))
    .catch(error =&amp;gt; console.error(error));
```

## Promise Chaining Concept

One of the most significant advantages of promises is the ability to chain them. This allows for a sequence of asynchronous operations to be performed in a clear and structured manner.

### Example of Promise Chaining

```javascript
fetchData()
    .then(data =&amp;gt; processData(data))
    .then(processedData =&amp;gt; saveData(processedData))
    .catch(error =&amp;gt; console.error("Error:", error));
```

In this example, each asynchronous function returns a promise, allowing for a clean flow of operations.

## Comparing Promises with Callbacks

While callbacks are a traditional method for handling asynchronous operations, they can lead to complex and hard-to-read code structures, often referred to as "callback hell." In contrast, promises provide a more elegant solution:

- **Readability**: Promises allow for a more linear and readable code structure.
- **Error Handling**: Promises centralize error handling, making it easier to manage and debug.

### Diagram: Callback vs. Promise Comparison

`

```artifact
id: callback-vs-promise-comparison
name: Callback vs Promise Comparison
type: mermaid
content: |-
  graph TD;
      A[Callback] --&amp;gt; B[Callback Function];
      B --&amp;gt; C[Callback Hell];
      A --&amp;gt; D[Error Handling];
      D --&amp;gt; E[Complex Logic];
      F[Promise] --&amp;gt; G[Promise Creation];
      G --&amp;gt; H[Then Method];
      H --&amp;gt; I[Catch Method];
      F --&amp;gt; J[Chaining];
      J --&amp;gt; K[Readable Logic];
```

`

## Conclusion

JavaScript promises are a fundamental tool for managing asynchronous operations. By understanding their lifecycle, how to handle success and failure, and the advantages they offer over callbacks, developers can write cleaner, more maintainable code. Emphasizing readability and structured error handling, promises are essential for modern JavaScript development.

Feel free to edit and humanize this content as needed before publishing it on Hashnode or a similar platform!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>chaicode</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Protecting Your macOS: How to Find Exactly Which IPs Are Trying to Attack Your System (And Stop Them)</title>
      <dc:creator>Bhupesh Chandra Joshi</dc:creator>
      <pubDate>Mon, 20 Apr 2026 10:09:42 +0000</pubDate>
      <link>https://forem.com/bhupeshchandrajoshi/protecting-your-macos-how-to-find-exactly-which-ips-are-trying-to-attack-your-system-and-stop-3ink</link>
      <guid>https://forem.com/bhupeshchandrajoshi/protecting-your-macos-how-to-find-exactly-which-ips-are-trying-to-attack-your-system-and-stop-3ink</guid>
      <description>&lt;h1&gt;
  
  
  Protecting Your macOS: How to Find Exactly Which IPs Are Trying to Attack Your System (And Stop Them)
&lt;/h1&gt;

&lt;p&gt;As developers, remote workers, and tech enthusiasts, many of us rely on macOS for its sleek design, robust performance, and security features. But as secure as macOS is, it’s not immune to attacks. Whether you’re working from a coffee shop, running a home server, or managing an enterprise fleet, understanding how to protect your macOS from malicious activity is crucial.&lt;/p&gt;

&lt;p&gt;Today, we’ll dive deep into macOS’s file system and security tools to uncover how you can identify and block IPs attempting to attack your system. This isn’t a basic tutorial — it’s a real-world investigation into macOS internals. By the end, you’ll have actionable insights and practical steps to improve your system’s security.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;Imagine you’re working on public Wi-Fi, hosting a personal project on your macOS, or simply SSH-ing into your machine remotely. Attackers often scan IP ranges to find vulnerable systems. Brute-force SSH attempts, unauthorized access attempts, and even DNS manipulation can target your macOS. The good news? macOS provides powerful tools and logs that can help you detect and stop these attacks — if you know where to look.&lt;/p&gt;

&lt;p&gt;Let’s dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Unified Logging System: Where macOS Hides Attack Logs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt; macOS’s unified logging system consolidates logs from various system components, including network events, authentication attempts, and system processes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it exists:&lt;/strong&gt; Apple designed this system to make debugging and monitoring easier for developers and system administrators. Instead of scattered log files, you get a centralized repository that’s queryable with &lt;code&gt;log&lt;/code&gt; commands.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-world problem it solves:&lt;/strong&gt; Attackers often try brute-forcing SSH credentials or exploiting open ports. The unified logging system records failed login attempts, connection errors, and other suspicious activities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Surprising insight:&lt;/strong&gt; By using advanced predicates, you can filter logs to pinpoint specific IP addresses attempting to access your system. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;id: macos_security_blog
name: Protecting Your macOS Blog Post
type: markdown
content: |-
  # Protecting Your macOS: How to Find Exactly Which IPs Are Trying to Attack Your System (And Stop Them)

  As developers, remote workers, and tech enthusiasts, many of us rely on macOS for its sleek design, robust performance, and security features. But as secure as macOS is, it’s not immune to attacks. Whether you’re working from a coffee shop, running a home server, or managing an enterprise fleet, understanding how to protect your macOS from malicious activity is crucial.

  Today, we’ll dive deep into macOS’s file system and security tools to uncover how you can identify and block IPs attempting to attack your system. This isn’t a basic tutorial — it’s a real-world investigation into macOS internals. By the end, you’ll have actionable insights and practical steps to improve your system’s security.

  ## Why This Matters

  Imagine you’re working on public Wi-Fi, hosting a personal project on your macOS, or simply SSH-ing into your machine remotely. Attackers often scan IP ranges to find vulnerable systems. Brute-force SSH attempts, unauthorized access attempts, and even DNS manipulation can target your macOS. The good news? macOS provides powerful tools and logs that can help you detect and stop these attacks — if you know where to look.

  Let’s dive in.

  ## 1. Unified Logging System: Where macOS Hides Attack Logs

  **What it does:** macOS’s unified logging system consolidates logs from various system components, including network events, authentication attempts, and system processes.

  **Why it exists:** Apple designed this system to make debugging and monitoring easier for developers and system administrators. Instead of scattered log files, you get a centralized repository that’s queryable with `log` commands.

  **Real-world problem it solves:** Attackers often try brute-forcing SSH credentials or exploiting open ports. The unified logging system records failed login attempts, connection errors, and other suspicious activities.

  **Surprising insight:** By using advanced predicates, you can filter logs to pinpoint specific IP addresses attempting to access your system. For example:

  ```

`code.bash
  log show --predicate 'eventMessage contains "Failed to authenticate user"' --info
  `

```

  This command searches for failed authentication attempts. Pair it with additional predicates to extract the IP addresses behind these attempts.

  ## 2. Extracting Attacking IPs from Logs

  **What it does:** By analyzing logs in `/var/log/secure.log` or using the unified logging system, you can identify IP addresses associated with failed SSH login attempts or other suspicious activity.

  **Why it exists:** These logs are crucial for understanding who’s trying to access your system and whether they’re authorized.

  **Real-world problem it solves:** Knowing the source of attacks allows you to block them proactively using firewall rules.

  **Interesting insight:** While grepping through logs works, using structured queries with `log show` is far more effective and precise. For instance:

  ```

`code.bash
  log show --predicate 'eventMessage contains "sshd"' --info | grep "Invalid user"
  `

```

  This reveals invalid login attempts, making it easy to spot patterns in attacking IPs.

  ## 3. Application Layer Firewall (ALF) and Its Configuration

  **What it does:** The macOS Application Layer Firewall (ALF) monitors and controls network connections at the application level.

  **Why it exists:** ALF ensures that only authorized applications can accept incoming connections, reducing the attack surface.

  **Real-world problem it solves:** Attackers often exploit open ports or vulnerable applications. ALF helps mitigate these risks by blocking unauthorized connections.

  **Surprising insight:** The ALF configuration is stored in `/Library/Preferences/com.apple.alf.plist`. By inspecting this file, you can verify which apps are allowed to accept connections:

  ```

`code.bash
  sudo defaults read /Library/Preferences/com.apple.alf.plist
  `

```

  You can also enable stealth mode to prevent your macOS from responding to ping requests:

  ```

`code.bash
  sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setstealthmode on
  `

```

  ## 4. Packet Filter (pf) Rules: The Hidden Power of `/etc/pf.conf`

  **What it does:** The packet filter (pf) is a powerful macOS tool for managing network traffic. It allows you to define rules for blocking or allowing specific IPs.

  **Why it exists:** pf provides granular control over network traffic, making it ideal for advanced users who need custom firewall configurations.

  **Real-world problem it solves:** Want to block a specific IP that’s been attacking your system? Add a rule to `/etc/pf.conf`:

  ```

`code.bash
  sudo nano /etc/pf.conf
  `

```

  Add a block rule:
  ```


  block in quick from &amp;lt;attacking_ip&amp;gt;


  ```

  Reload pf:
  ```

`code.bash
  sudo pfctl -f /etc/pf.conf
  sudo pfctl -e
  `

```

  **Surprising insight:** pf also supports anchor files for modular configurations. This is useful for managing complex rulesets.

  ## 5. Secrets Inside `/var/db/`

  **What it does:** The `/var/db/` directory contains critical system data, including firewall states, quarantine settings, and more.

  **Why it exists:** macOS uses this directory to store persistent system configurations.

  **Real-world problem it solves:** Attackers often target this directory to disable security features or modify settings. Monitoring changes here can help detect tampering.

  **Interesting insight:** The `firewall` subdirectory within `/var/db/` contains active firewall rules. Regularly inspect this directory for unauthorized changes.

  ## 6. System Integrity Protection (SIP): The Double-Edged Sword

  **What it does:** SIP is a macOS feature that prevents modification of critical system files.

  **Why it exists:** SIP protects your macOS from malware and unauthorized changes.

  **Real-world problem it solves:** Without SIP, attackers could easily disable security features or inject malicious code into system files.

  **Surprising insight:** While SIP is invaluable for security, it also limits your ability to inspect certain files and configurations. For advanced investigations, you may need to temporarily disable SIP (not recommended for regular users).

  ## 7. LaunchDaemons for Custom Monitoring

  **What it does:** LaunchDaemons allow you to create custom services that run in the background.

  **Why it exists:** macOS uses LaunchDaemons to manage system processes and scheduled tasks.

  **Real-world problem it solves:** You can create a custom daemon to monitor logs and automatically block attacking IPs.

  **Interesting insight:** Place your daemon configuration in `/Library/LaunchDaemons/` and use `launchctl` to load it.

  ## 8. DNS and Host Configurations

  **What it does:** Files like `/etc/hosts` and `/etc/resolv.conf` control DNS resolution and host mappings.

  **Why it exists:** These files allow macOS to resolve domain names and manage local network configurations.

  **Real-world problem it solves:** Attackers can manipulate DNS settings to redirect traffic or spoof domains. Regularly inspect these files for unauthorized changes.

  **Interesting insight:** You can block malicious domains by adding entries to `/etc/hosts`:
  ```


  0.0.0.0 malicious-domain.com


  ```

  ## 9. Hidden Security Folders: Gems Most Users Miss

  **What it does:** macOS has several hidden security-related folders, such as `/private/var/log/asl/` and `/private/etc/security/`.

  **Why it exists:** These folders store logs and configurations for various security features.

  **Real-world problem it solves:** Monitoring these folders can reveal unusual activity or tampering attempts.

  **Interesting insight:** The `/private/var/log/asl/` folder contains archived logs that may provide additional context for attacks.

  ## Actionable Tips to Protect Your macOS

  1. Regularly inspect your logs using `log show` with specific predicates.
  2. Enable macOS’s Application Layer Firewall and set it to stealth mode.
  3. Use pf rules to block attacking IPs and manage traffic effectively.
  4. Monitor `/var/db/` and other critical directories for unauthorized changes.
  5. Add malicious domains to `/etc/hosts` to prevent DNS-based attacks.

  ## Share Your Discoveries!

  macOS is a treasure trove of security features waiting to be explored. What hidden gems have you discovered in your system? Share your insights in the comments — let’s learn from each other and build a stronger, more secure community.

  Together, we can make our macOS systems safer for everyone.
```

`

### Explanation
This blog post is structured for readability and engagement, following the Hashnode-friendly format with clear headings, short paragraphs, and actionable insights. It adheres to the rules outlined in the prompt, providing in-depth explanations for each finding, ethical guidelines, and a call-to-action for community interaction.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>chaicode</category>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Linux File System Hunting: I Dug So Deep I Found Secrets That Could Get This Post Taken Down</title>
      <dc:creator>Bhupesh Chandra Joshi</dc:creator>
      <pubDate>Mon, 20 Apr 2026 09:54:52 +0000</pubDate>
      <link>https://forem.com/bhupeshchandrajoshi/linux-file-system-hunting-i-dug-so-deep-i-found-secrets-that-could-get-this-post-taken-down-28pb</link>
      <guid>https://forem.com/bhupeshchandrajoshi/linux-file-system-hunting-i-dug-so-deep-i-found-secrets-that-could-get-this-post-taken-down-28pb</guid>
      <description>&lt;h1&gt;
  
  
  Linux File System Hunting: Awareness Blog
&lt;/h1&gt;

&lt;p&gt;It was 2 a.m., and I’d just cracked open my third cup of coffee. The terminal glowed in the dark like a portal to some forbidden realm. I wasn’t just SSH’ing into a Linux server—I was about to dive headfirst into the guts of the operating system, peeling back layers most people don’t even know exist. &lt;/p&gt;

&lt;p&gt;I didn’t plan to write this post. I was just curious. But what I found? Holy crap. I gasped more than once. I laughed, I cursed, and I felt a creeping paranoia that made me want to unplug every server I’ve ever touched. &lt;/p&gt;

&lt;p&gt;This isn’t your typical “how to use Linux” tutorial. This is raw, unfiltered, late-night detective work—an investigation into the file system-level DNA of Linux. I’m talking about the files and subsystems that control literally everything. Some of these discoveries are so dangerous, they could make a black-hat hacker salivate. Others will make you rethink every security measure you’ve ever implemented. &lt;/p&gt;

&lt;p&gt;So grab a coffee, fire up a terminal, and let’s go hunting. You will NOT believe what I found.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Hidden Power of &lt;code&gt;/etc/resolv.conf&lt;/code&gt;: DNS Poisoning Is Easier Than You Think&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let’s kick things off with a file that controls one of the most fundamental aspects of your server: DNS resolution. You’ve probably seen &lt;code&gt;/etc/resolv.conf&lt;/code&gt; before—it’s where your server decides which DNS servers to query when resolving domain names. But here’s the kicker: this file is deceptively simple, yet terrifyingly powerful.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What It Does&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Under the hood, this file tells your system where to look for DNS answers. It’s usually just a few lines, like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nameserver 8.8.8.8
nameserver 8.8.4.4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple, right? Wrong.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why Linux Created It&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;DNS is the backbone of the internet. Without it, your server wouldn’t know that &lt;code&gt;google.com&lt;/code&gt; maps to &lt;code&gt;142.250.190.78&lt;/code&gt;. &lt;code&gt;/etc/resolv.conf&lt;/code&gt; centralizes DNS configuration so every application knows where to ask for IP addresses.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Jaw-Dropping Insight&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Here’s the wild part: this file can be silently poisoned. If an attacker gains access to your system, they can redirect DNS queries to a malicious server, hijacking every domain lookup. Imagine typing &lt;code&gt;bank.com&lt;/code&gt; and landing on an attacker’s phishing page instead. Worse, automated systems relying on domain names can be tricked into downloading malware or leaking sensitive data.&lt;/p&gt;

&lt;p&gt;Run this command to see the raw DNS queries in action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;tcpdump &lt;span class="nt"&gt;-i&lt;/span&gt; any port 53
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll see every DNS query your server makes. If you notice queries going somewhere unexpected, you’ve got a problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why This Matters for Security&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If you’re not locking down &lt;code&gt;/etc/resolv.conf&lt;/code&gt;, you’re practically begging for DNS hijacking. Use tools like &lt;code&gt;chattr +i /etc/resolv.conf&lt;/code&gt; to make the file immutable and monitor it religiously.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Secret Life of &lt;code&gt;/proc/&amp;lt;pid&amp;gt;/environ&lt;/code&gt;: Spying on Process Secrets&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You think you know what’s running on your server? Think again. The &lt;code&gt;/proc&lt;/code&gt; filesystem is like a living autopsy of your system, and one file in particular—&lt;code&gt;/proc/&amp;lt;pid&amp;gt;/environ&lt;/code&gt;—blew my mind.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What It Does&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This file shows the environment variables of any running process. Yes, &lt;strong&gt;any&lt;/strong&gt; process. Want to know what secrets a specific app is holding in its environment? This is where you look.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why Linux Created It&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Environment variables are crucial for processes to function. They store configuration data, credentials, and runtime-specific values. &lt;code&gt;/proc/&amp;lt;pid&amp;gt;/environ&lt;/code&gt; is a window into that world, meant for debugging and monitoring. But it’s also a security nightmare.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Jaw-Dropping Insight&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Run this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /proc/&amp;lt;pid&amp;gt;/environ | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s1"&gt;'\0'&lt;/span&gt; &lt;span class="s1"&gt;'\n'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;&amp;lt;pid&amp;gt;&lt;/code&gt; with the process ID of, say, your web server. You’ll see everything: database credentials, API keys, and other sensitive data. If an attacker gets access to your server, they can scrape this file to steal secrets without even touching your codebase.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why This Matters for Security&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Environment variables are often overlooked in security audits. If you’re not sanitizing them or using tools like &lt;code&gt;systemd&lt;/code&gt; to lock them down, you’re exposing your crown jewels.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Routing Table Secrets: The Ghosts of &lt;code&gt;/proc/net/route&lt;/code&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Ever wondered how your server decides where to send packets? The answer lies in &lt;code&gt;/proc/net/route&lt;/code&gt;. This file is a real-time view of your kernel’s routing table, and it’s a goldmine for anyone looking to understand (or exploit) your network.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What It Does&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;It shows the routes your server uses to send packets to different networks. Each line represents a route, with columns for destination, gateway, netmask, and more.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why Linux Created It&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Routing is the heart of networking. Without a routing table, your server wouldn’t know how to send packets to their destinations. &lt;code&gt;/proc/net/route&lt;/code&gt; lets you peek into the kernel’s routing logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Jaw-Dropping Insight&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Run this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /proc/net/route
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll see something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Iface   Destination Gateway   Flags RefCnt Use Metric Mask
eth0    00000000    01010101  0003  0      0   0     00000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those hex values? They’re the IP addresses of your default gateway and routes. An attacker could use this info to map your network and launch targeted attacks.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why This Matters for Security&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If &lt;code&gt;/proc/net/route&lt;/code&gt; is exposed to unauthorized users, you’re handing them a blueprint of your network. Lock down permissions and monitor access.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Underrated Danger of &lt;code&gt;/etc/passwd&lt;/code&gt; and &lt;code&gt;/etc/shadow&lt;/code&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You’ve heard of these files before, but do you really understand their implications? They’re the heart of user management on Linux, and they’re both incredibly powerful and dangerously vulnerable.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What They Do&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/etc/passwd&lt;/code&gt;: Stores user account info, including usernames and home directories.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/etc/shadow&lt;/code&gt;: Stores hashed passwords and password policies.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why Linux Created Them&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;User authentication is the cornerstone of system security. These files provide a centralized way to manage users and their credentials.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Jaw-Dropping Insight&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Run this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/passwd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll see something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;root:x:0:0:root:/root:/bin/bash
user:x:1000:1000:User:/home/user:/bin/bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;x&lt;/code&gt; in the second column means the password is stored in &lt;code&gt;/etc/shadow&lt;/code&gt;. But here’s the scary part: if &lt;code&gt;/etc/shadow&lt;/code&gt; is compromised, an attacker can brute-force your hashed passwords offline.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why This Matters for Security&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Permissions on these files are everything. Make sure only &lt;code&gt;root&lt;/code&gt; can access &lt;code&gt;/etc/shadow&lt;/code&gt;, and audit them regularly for unauthorized changes.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Inside &lt;code&gt;/boot&lt;/code&gt;: The Keys to the Kingdom&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;/boot&lt;/code&gt; directory is where your system’s heart lies. It contains the kernel and bootloader configs—mess with this, and you can bring the entire system to its knees.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What It Does&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This is where your system stores critical files for booting, like the kernel (&lt;code&gt;vmlinuz&lt;/code&gt;) and GRUB configs.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why Linux Created It&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Without a dedicated boot directory, your system wouldn’t know how to start. It’s the first thing the computer looks at when powering on.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Jaw-Dropping Insight&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Run this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; /boot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll see files like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vmlinuz-5.15.0-67-generic
initrd.img-5.15.0-67-generic
grub/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modify GRUB configs, and you can change boot parameters, disable security features, or even redirect the system to boot into a malicious kernel.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why This Matters for Security&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Lock down &lt;code&gt;/boot&lt;/code&gt; permissions. Better yet, encrypt your boot partition. If an attacker gets access here, it’s game over.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Puppet Master: &lt;code&gt;/etc/systemd/system&lt;/code&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Systemd runs the show on modern Linux systems, and its configuration files are the puppet strings. If you’ve ever wondered how your server magically starts services on boot, this is where it happens.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What It Does&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This directory contains unit files that define how services are started, stopped, and managed. It’s the brain of your server’s automation.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why Linux Created It&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Systemd replaced older init systems to provide a unified way to manage services. It’s powerful, but with great power comes great responsibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Jaw-Dropping Insight&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Run this command to list all active services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl list-units &lt;span class="nt"&gt;--type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now check the contents of a suspicious unit file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight systemd"&gt;&lt;code&gt;&lt;span class="err"&gt;cat&lt;/span&gt; &lt;span class="err"&gt;/etc/systemd/system/my-service.service&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might find something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Service]
ExecStart=/usr/bin/my-app --config /etc/my-app.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If an attacker modifies this file, they can inject malicious commands that execute on every boot.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why This Matters for Security&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Audit your unit files regularly, and use &lt;code&gt;systemctl status&lt;/code&gt; to monitor for unexpected changes. A compromised service file is a stealthy way to persist malware.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion: The Hunt Never Ends&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I’ve barely scratched the surface here. Linux is a beautiful, terrifying beast, and every file in its ecosystem has a story—a purpose, a secret, a vulnerability. If you’re a sysadmin, developer, or security nerd, you owe it to yourself to dive deeper. &lt;/p&gt;

&lt;p&gt;Hardening a Linux server isn’t just about running commands—it’s about understanding the system as a living, breathing organism. Every file, every process, every packet tells a story. And if you’re not listening, someone else will—someone who doesn’t have your best interests in mind.&lt;/p&gt;

&lt;p&gt;So what are you waiting for? Fire up your terminal, start hunting, and remember: the deeper you dig, the darker it gets. Stay paranoid, stay caffeinated, and stay safe.&lt;/p&gt;




</description>
      <category>linux</category>
      <category>chaicode</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Linux File System Hunting: What I Discovered Digging Under the Hood (Beyond the Basics)</title>
      <dc:creator>Bhupesh Chandra Joshi</dc:creator>
      <pubDate>Mon, 20 Apr 2026 09:45:41 +0000</pubDate>
      <link>https://forem.com/bhupeshchandrajoshi/linux-file-system-hunting-what-i-discovered-digging-under-the-hood-beyond-the-basics-15kc</link>
      <guid>https://forem.com/bhupeshchandrajoshi/linux-file-system-hunting-what-i-discovered-digging-under-the-hood-beyond-the-basics-15kc</guid>
      <description>&lt;p&gt;As a Linux enthusiast, I’ve always been fascinated by how this operating system is structured — it feels like peeling back the layers of a well-designed machine. So one day, I decided to step into the role of a “system investigator” and dive deep into the Linux file system on my Ubuntu 24.04 LTS machine. My goal? To understand how the OS actually works under the hood, beyond the basics we all know.&lt;/p&gt;

&lt;p&gt;This wasn’t just a theoretical exercise. I spent hours poking around directories, opening files, and connecting dots between what I saw and what I’d learned over the years. What surprised me most was how every file and folder has a story — a purpose in the grand design of Linux. If you’re a developer, DevOps engineer, or just someone curious about the inner workings of your system, understanding these details can make you a much better problem solver.&lt;/p&gt;

&lt;p&gt;In this post, I’ll share &lt;strong&gt;8 meaningful discoveries&lt;/strong&gt; I made during my exploration. These aren’t just random files or commands — they’re insights into how Linux operates, solves real-world problems, and keeps your system humming along. Let’s dive in!&lt;/p&gt;




&lt;h2&gt;
  
  
  1. &lt;strong&gt;The Mighty /etc Directory: Linux’s Brain&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The &lt;code&gt;/etc&lt;/code&gt; directory is home to configuration files that control almost every aspect of your system — from user accounts to network settings to services. It’s like Linux’s brain, where all the critical decisions are stored.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it exists:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Linux is designed to be modular and customizable. Instead of hardcoding settings into the kernel, &lt;code&gt;/etc&lt;/code&gt; allows admins to tweak configurations without touching the core system. This makes Linux flexible and adaptable for different environments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-world problem it solves:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Imagine you’re setting up a server with custom DNS or user permissions. Instead of rebuilding the system, you can modify files in &lt;code&gt;/etc&lt;/code&gt; to tailor the OS to your needs. For example, &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; lets you tweak SSH settings to harden your server against attacks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interesting insight:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I opened &lt;code&gt;/etc/environment&lt;/code&gt; and realized it’s where global environment variables are set. This means every user and process inherits these variables, making it a powerful tool for system-wide configuration. It’s a reminder that even simple files can have a huge impact.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. &lt;strong&gt;DNS Configuration: The Gatekeeper of Networking&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Files like &lt;code&gt;/etc/resolv.conf&lt;/code&gt; and &lt;code&gt;/etc/hosts&lt;/code&gt;, along with systemd-resolved, manage how your system resolves domain names into IP addresses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it exists:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Without DNS, you’d be stuck typing IP addresses into your browser — not very practical! These files ensure your system knows where to look when resolving names like &lt;code&gt;google.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-world problem it solves:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
When I was troubleshooting a network issue, I discovered that a misconfigured &lt;code&gt;/etc/resolv.conf&lt;/code&gt; can break internet access. It’s also where you can manually set DNS servers (like Google’s &lt;code&gt;8.8.8.8&lt;/code&gt;) to bypass ISP restrictions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interesting insight:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I learned that &lt;code&gt;/etc/hosts&lt;/code&gt; can be used for quick fixes — like redirecting specific domains to localhost for testing. But what really surprised me was systemd-resolved’s role in caching DNS queries, speeding up repeated lookups.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. &lt;strong&gt;Routing Table: The Map of Network Traffic&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The routing table, accessible via &lt;code&gt;/proc/net/route&lt;/code&gt; or commands like &lt;code&gt;ip route&lt;/code&gt;, shows how packets are routed through your network interfaces.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it exists:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Routing is essential for communication. Without it, your system wouldn’t know whether to send packets to your Wi-Fi, Ethernet, or a specific gateway.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-world problem it solves:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
When debugging connectivity issues, I found that checking the routing table can explain why packets aren’t reaching their destination. For example, a missing default gateway can prevent internet access entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interesting insight:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I was surprised to see how dynamic the routing table is. When I connected to a VPN, the table instantly updated to route traffic through the VPN’s gateway. It’s like watching your system adapt in real time.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. &lt;strong&gt;System Logs: The Black Box of Linux&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
System logs, stored in &lt;code&gt;/var/log&lt;/code&gt; and accessible via tools like &lt;code&gt;journalctl&lt;/code&gt;, record everything happening in your system — from kernel messages to app errors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it exists:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Logs are the first place to look when something goes wrong. They’re like a black box for your system, capturing events that help you troubleshoot issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-world problem it solves:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
When my system froze during boot, I used &lt;code&gt;journalctl&lt;/code&gt; to find errors related to a misconfigured service. Without logs, I’d have been flying blind.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interesting insight:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I discovered that &lt;code&gt;/var/log/syslog&lt;/code&gt; is like a diary for your system’s core operations, while &lt;code&gt;/var/log/auth.log&lt;/code&gt; is a goldmine for tracking login attempts. It’s a reminder of how much data your system quietly collects.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. &lt;strong&gt;User Management Files: The DNA of Accounts&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Files like &lt;code&gt;/etc/passwd&lt;/code&gt;, &lt;code&gt;/etc/shadow&lt;/code&gt;, and &lt;code&gt;/etc/group&lt;/code&gt; store information about users, passwords, and groups.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it exists:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Linux is a multi-user system, so it needs a way to manage who can access what. These files provide a centralized way to define users and their permissions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-world problem it solves:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
When I accidentally locked myself out of my system, I learned that &lt;code&gt;/etc/shadow&lt;/code&gt; stores hashed passwords. With root access, I was able to reset my password and regain control.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interesting insight:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I was surprised by how readable &lt;code&gt;/etc/passwd&lt;/code&gt; is. It’s a simple text file that lists users and their home directories. But the real security lies in &lt;code&gt;/etc/shadow&lt;/code&gt;, where passwords are encrypted. It’s a clever separation of concerns.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. &lt;strong&gt;The /proc Filesystem: A Live Kernel X-Ray&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The &lt;code&gt;/proc&lt;/code&gt; directory contains virtual files that provide a live view into the kernel’s inner workings — like CPU info, memory usage, and process details.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it exists:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Linux is built on transparency. Instead of hiding the kernel’s state, &lt;code&gt;/proc&lt;/code&gt; lets you peek inside and see what’s happening in real time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-world problem it solves:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
When my CPU usage spiked unexpectedly, I opened &lt;code&gt;/proc/cpuinfo&lt;/code&gt; to check my processor’s specs and &lt;code&gt;/proc/meminfo&lt;/code&gt; to see if I was running out of RAM. It’s like having a diagnostic tool built into the filesystem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interesting insight:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I found &lt;code&gt;/proc/&amp;lt;pid&amp;gt;&lt;/code&gt; directories fascinating. Each running process has its own folder, showing everything from memory maps to open file descriptors. It’s a reminder of how deeply Linux integrates processes into its design.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. &lt;strong&gt;Device Handling in /dev: Where Hardware Meets Software&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The &lt;code&gt;/dev&lt;/code&gt; directory contains special files that represent hardware devices, like disks, terminals, and even random number generators.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it exists:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Linux treats devices as files, making it easy to interact with hardware using standard tools. For example, &lt;code&gt;/dev/null&lt;/code&gt; acts as a data sink, while &lt;code&gt;/dev/random&lt;/code&gt; provides entropy for cryptographic operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-world problem it solves:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
When I needed to wipe sensitive data, I used &lt;code&gt;/dev/null&lt;/code&gt; to overwrite files. It’s also where you’ll find disk partitions, like &lt;code&gt;/dev/sda1&lt;/code&gt;, when setting up storage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interesting insight:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I discovered that &lt;code&gt;/dev/random&lt;/code&gt; can block if there’s not enough entropy, while &lt;code&gt;/dev/urandom&lt;/code&gt; doesn’t. This trade-off between security and speed is a fascinating design choice.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. &lt;strong&gt;Boot Configs in /boot: The Startup Playbook&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The &lt;code&gt;/boot&lt;/code&gt; directory contains the files needed to boot your system, including the kernel and GRUB configurations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it exists:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The boot process is complex, involving multiple stages. &lt;code&gt;/boot&lt;/code&gt; ensures all the necessary components are available to get your system up and running.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-world problem it solves:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
When my system failed to boot, I found the issue in &lt;code&gt;/boot/grub/grub.cfg&lt;/code&gt;. A typo in the configuration file was preventing GRUB from loading the kernel. Fixing it brought my system back to life.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interesting insight:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I learned that &lt;code&gt;/boot/vmlinuz&lt;/code&gt; is the compressed kernel image. It’s fascinating how this tiny file contains the core of the operating system. It’s a reminder of Linux’s efficiency.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion: The Living Blueprint of Linux
&lt;/h2&gt;

&lt;p&gt;Exploring the Linux file system felt like uncovering a treasure map. Each directory and file isn’t just storage — it’s a living blueprint of how the OS operates. From DNS settings to kernel diagnostics to boot configurations, every piece works together to create a seamless experience.&lt;/p&gt;

&lt;p&gt;What surprised me most was how interconnected everything is. For example, a misconfigured file in &lt;code&gt;/etc&lt;/code&gt; can ripple through the system, breaking services or even preventing boot. This kind of “hunting” makes you a better developer or sysadmin because it teaches you to think like the OS — to understand how the parts fit together.&lt;/p&gt;

&lt;p&gt;One curious discovery I’m still exploring is the difference between &lt;code&gt;/dev/random&lt;/code&gt; and &lt;code&gt;/dev/urandom&lt;/code&gt;. Why does Linux offer two options, and how do they impact cryptographic security? If you’ve got insights, I’d love to hear them.&lt;/p&gt;

&lt;p&gt;So here’s my challenge to you: fire up your Linux machine, pick a directory, and start hunting. You’ll be amazed at what you discover. And when you do, share your findings — I’d love to hear your stories!&lt;/p&gt;

</description>
      <category>chaicode</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>node</category>
    </item>
  </channel>
</rss>
