<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Rohit Chornele's blog]]></title><description><![CDATA[This is about the technical articles mostly related to web development.]]></description><link>https://blog.rohitchornele.online</link><generator>RSS for Node</generator><lastBuildDate>Wed, 10 Jun 2026 03:44:48 GMT</lastBuildDate><atom:link href="https://blog.rohitchornele.online/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[JWT Authentication in Node.js Explained Simply]]></title><description><![CDATA[Authentication is one of the most important concepts in backend development.Whenever users log into an application, the server needs a secure way to identify them in future requests.
Modern applicatio]]></description><link>https://blog.rohitchornele.online/jwt-authentication-in-node-js-explained-simply</link><guid isPermaLink="true">https://blog.rohitchornele.online/jwt-authentication-in-node-js-explained-simply</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[authentication]]></category><category><![CDATA[JWT]]></category><category><![CDATA[jsonwebtoken]]></category><dc:creator><![CDATA[Rohit Chornele]]></dc:creator><pubDate>Sun, 10 May 2026 18:13:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6688fdd59dfed4afe8f5b269/011cb093-aa92-4fdb-b071-507e8a521ac3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Authentication is one of the most important concepts in backend development.<br />Whenever users log into an application, the server needs a secure way to identify them in future requests.</p>
<p>Modern applications commonly use <strong>JWT (JSON Web Token)</strong> for this purpose because it is simple, scalable, and works very well with APIs.</p>
<p>In this article, we’ll understand what authentication means, what JWT is, how JWT authentication works in Node.js, and how protected routes use tokens for authorization.</p>
<hr />
<h2>What Authentication Means</h2>
<p>Authentication is the process of verifying a user’s identity.</p>
<p>Example:</p>
<p>User enters:</p>
<ul>
<li><p>Email</p>
</li>
<li><p>Password</p>
</li>
</ul>
<p>The server checks whether the credentials are correct.</p>
<p>If valid:</p>
<p>User is authenticated</p>
<p>After authentication, the server must remember who the user is for future requests.</p>
<h3>Why Authentication is Needed</h3>
<p>Imagine a social media application.</p>
<p>Without authentication:</p>
<ul>
<li><p>anyone could access private accounts</p>
</li>
<li><p>anyone could update user profiles</p>
</li>
<li><p>anyone could delete posts</p>
</li>
</ul>
<p>Authentication ensures that only verified users can access protected resources.</p>
<h3>Traditional Authentication Problem</h3>
<p>HTTP is stateless by default.</p>
<p>This means every request is treated independently.</p>
<p>Example:</p>
<pre><code class="language-javascript">GET /profile
</code></pre>
<p>The server does not automatically know who sent the request.</p>
<p>JWT solves this problem using token-based authentication.</p>
<hr />
<h2>What is JWT?</h2>
<p>JWT stands for:</p>
<pre><code class="language-plaintext">JSON Web Token
</code></pre>
<p>A JWT is a secure token used to identify authenticated users.</p>
<p>After login:</p>
<ol>
<li><p>Server creates a token</p>
</li>
<li><p>Token is sent to the client</p>
</li>
<li><p>Client stores the token</p>
</li>
<li><p>Client sends token with future requests</p>
</li>
<li><p>Server verifies the token</p>
</li>
</ol>
<h3>JWT Authentication Flow</h3>
<pre><code class="language-javascript">
  User Login
      ↓
  Server Verifies Credentials
      ↓
  JWT Token Generated
      ↓
  Token Sent to Client
      ↓
  Client Stores Token
      ↓
  Client Sends Token in Requests
      ↓
  Server Verifies Token
      ↓
  Protected Data Returned
</code></pre>
<h3>JWT is Stateless Authentication</h3>
<p>JWT authentication is called <strong>stateless</strong> because the server usually does not store login session data.</p>
<p>Instead:</p>
<pre><code class="language-javascript">Token itself contains user information
</code></pre>
<p>This makes JWT systems scalable and API-friendly.</p>
<hr />
<h2>Structure of a JWT</h2>
<p>A JWT contains three parts:</p>
<pre><code class="language-javascript">HEADER.PAYLOAD.SIGNATURE
</code></pre>
<p>Example:</p>
<pre><code class="language-javascript">eyJhbGciOi...
.
eyJpZCI6...
.
SflKxwRJS...
</code></pre>
<p>Each section has a specific purpose.</p>
<h3>1. Header</h3>
<p>The header contains metadata about the token.</p>
<p>Example:</p>
<pre><code class="language-json">{
  "alg": "HS256",
  "typ": "JWT"
}
</code></pre>
<p>It specifies:</p>
<ul>
<li><p>token type</p>
</li>
<li><p>signing algorithm</p>
</li>
</ul>
<h3>2. Payload</h3>
<p>The payload contains user-related data.</p>
<p>Example:</p>
<pre><code class="language-json">{
  "id": "123",
  "email": "user@example.com",
  "role": "user"
}
</code></pre>
<p>This information is called <strong>claims</strong>.</p>
<p>Important:</p>
<p>JWT payload is encoded, not encrypted.</p>
<p>Do not store:</p>
<ul>
<li><p>passwords</p>
</li>
<li><p>sensitive secrets</p>
</li>
<li><p>confidential information</p>
</li>
</ul>
<h3>3. Signature</h3>
<p>The signature verifies that the token was not modified.</p>
<p>The server creates it using:</p>
<ul>
<li><p>header</p>
</li>
<li><p>payload</p>
</li>
<li><p>secret key</p>
</li>
</ul>
<p>This ensures token integrity.</p>
<hr />
<h2>Login flow using JWT</h2>
<h3>Creating a JWT Token</h3>
<p>Example:</p>
<pre><code class="language-javascript">
import jwt from "jsonwebtoken";

const token = jwt.sign(
    {
        id: user._id,
        email: user.email
    },
    process.env.JWT_SECRET,
    {
        expiresIn: "7d"
    }
);
</code></pre>
<h3>Understanding the Parameters</h3>
<p><strong>Payload :</strong></p>
<pre><code class="language-javascript">{
    id: user._id,
    email: user.email
}
</code></pre>
<p>Data stored inside the token.</p>
<p><strong>Secret Key :</strong></p>
<pre><code class="language-javascript">
process.env.JWT_SECRET
</code></pre>
<p>Used to sign and verify tokens.</p>
<p><strong>Expiration Time :</strong></p>
<pre><code class="language-javascript">expiresIn: "7d"
</code></pre>
<p>Defines how long the token remains valid.</p>
<h3>Sending JWT to Client</h3>
<p>After successful login:</p>
<pre><code class="language-javascript">res.json({
    token
});
</code></pre>
<p>The frontend stores the token.</p>
<p>Usually in:</p>
<ul>
<li><p>localStorage</p>
</li>
<li><p>sessionStorage</p>
</li>
<li><p>HTTP-only cookies</p>
</li>
</ul>
<hr />
<h2>Sending Token with Requests</h2>
<p>The client sends the token in request headers.</p>
<p>Example:</p>
<pre><code class="language-javascript">Authorization: Bearer jwt_token_here
</code></pre>
<p>This is the standard JWT authorization format.</p>
<hr />
<h2>Protecting Routes Using JWT</h2>
<p>Protected routes require valid tokens.</p>
<p>Example middleware:</p>
<pre><code class="language-javascript">import jwt from 'jsonwebtoken'

const authMiddleware = (req, res, next) =&gt; {

    const authHeader = req.headers.authorization;

    if (!authHeader) {
        return res.status(401).json({
            message: "Token missing"
        });
    }

    const token = authHeader.split(" ")[1];

    try {

        const decoded = jwt.verify(
            token,
            process.env.JWT_SECRET
        );

        req.user = decoded;

        next();

    } catch (error) {

        return res.status(401).json({
            message: "Invalid token"
        });
    }
};
</code></pre>
<h3>Using Protected Middleware</h3>
<p>Example route:</p>
<pre><code class="language-javascript">app.get("/profile", authMiddleware, (req, res) =&gt; {

    res.json({
        message: "Protected profile",
        user: req.user
    });

});
</code></pre>
<p>Only authenticated users can access this route.</p>
<h3>JWT Token Validation Lifecycle</h3>
<pre><code class="language-javascript">  Client Sends JWT
        ↓
  Server Extracts Token
        ↓
  JWT Signature Verified
        ↓
  Payload Decoded
        ↓
  Access Granted
</code></pre>
<hr />
<h2>Conclusion</h2>
<p>JWT authentication provides a modern and scalable way to handle user authentication in Node.js applications.</p>
<p>By understanding:</p>
<ul>
<li><p>how JWT works</p>
</li>
<li><p>token structure</p>
</li>
<li><p>login flow</p>
</li>
<li><p>protected routes</p>
</li>
<li><p>token verification</p>
</li>
</ul>
<p>you can build secure authentication systems for modern applications.</p>
<p>JWT may seem complicated initially, but once you understand the token flow, it becomes one of the most practical and widely used authentication approaches in backend development.</p>
]]></content:encoded></item><item><title><![CDATA[REST API Design Made Simple with Express.js]]></title><description><![CDATA[Modern web and mobile applications constantly communicate with servers to send and receive data.
Whenever you:

fetch users

create posts

update profiles

delete products


you are usually interactin]]></description><link>https://blog.rohitchornele.online/rest-api-design-made-simple-with-express-js</link><guid isPermaLink="true">https://blog.rohitchornele.online/rest-api-design-made-simple-with-express-js</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[REST API]]></category><category><![CDATA[Express]]></category><category><![CDATA[Node.js]]></category><dc:creator><![CDATA[Rohit Chornele]]></dc:creator><pubDate>Sun, 10 May 2026 17:52:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6688fdd59dfed4afe8f5b269/cf1e7bbe-b727-4858-97ef-1d0ef10a6990.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Modern web and mobile applications constantly communicate with servers to send and receive data.</p>
<p>Whenever you:</p>
<ul>
<li><p>fetch users</p>
</li>
<li><p>create posts</p>
</li>
<li><p>update profiles</p>
</li>
<li><p>delete products</p>
</li>
</ul>
<p>you are usually interacting with a <strong>REST API</strong>.</p>
<p>REST APIs are one of the most widely used ways to build backend services, and Express.js makes creating them simple and powerful.</p>
<p>In this article, we’ll understand what REST APIs are, how REST architecture works, HTTP methods, status codes, and how to design clean RESTful routes using Express.js.</p>
<hr />
<h2>What is a REST API?</h2>
<p>REST stands for:</p>
<pre><code class="language-javascript">Representational State Transfer
</code></pre>
<p>A REST API is a structured way for clients and servers to communicate over HTTP.</p>
<p>The client sends requests, and the server sends responses.</p>
<p>Example:</p>
<pre><code class="language-javascript">Frontend App  →  REST API  →  Database
</code></pre>
<p>The API acts as a bridge between the frontend and backend.</p>
<h3>Understanding APIs in Simple Words</h3>
<p>An API is like a waiter in a restaurant.</p>
<pre><code class="language-plaintext">Customer → Waiter → Kitchen
</code></pre>
<ul>
<li><p>Customer = Client</p>
</li>
<li><p>Waiter = API</p>
</li>
<li><p>Kitchen = Server/Database</p>
</li>
</ul>
<p>The client requests data through the API, and the server processes and returns a response.</p>
<h3>Resources in REST Architecture</h3>
<p>REST APIs are built around <strong>resources</strong>.</p>
<p>A resource is simply a piece of data or an entity in the system.</p>
<p>Examples:</p>
<ul>
<li><p>users</p>
</li>
<li><p>products</p>
</li>
<li><p>posts</p>
</li>
<li><p>orders</p>
</li>
</ul>
<p>In REST, resources are usually represented using nouns.</p>
<p>Good examples:</p>
<pre><code class="language-plaintext">/users
/products
/orders
</code></pre>
<p>Bad examples:</p>
<pre><code class="language-plaintext">/getUsers
/createProduct
/deleteOrder
</code></pre>
<p>REST focuses on resources, not actions.</p>
<hr />
<h2>HTTP Methods in REST APIs</h2>
<p>REST APIs use HTTP methods to define actions.</p>
<p>These methods map directly to CRUD operations.</p>
<table>
<thead>
<tr>
<th>CRUD Operation</th>
<th>HTTP Method</th>
<th>Purpose</th>
</tr>
</thead>
<tbody><tr>
<td>Create</td>
<td>POST</td>
<td>Add new data</td>
</tr>
<tr>
<td>Read</td>
<td>GET</td>
<td>Fetch data</td>
</tr>
<tr>
<td>Update</td>
<td>PUT</td>
<td>Update existing data</td>
</tr>
<tr>
<td>Delete</td>
<td>DELETE</td>
<td>Remove data</td>
</tr>
</tbody></table>
<h3>GET Request</h3>
<p>Used to fetch data.</p>
<p>Example:</p>
<pre><code class="language-javascript">GET /users
</code></pre>
<p>Express example:</p>
<pre><code class="language-javascript">
app.get("/users", (req, res) =&gt; {
    res.send("Fetch all users");
});
</code></pre>
<p>Fetch a single user:</p>
<pre><code class="language-javascript">
GET /users/1
</code></pre>
<h3>POST Request</h3>
<p>Used to create new data.</p>
<p>Example:</p>
<pre><code class="language-javascript">POST /users
</code></pre>
<p>Express example:</p>
<pre><code class="language-javascript">
app.post("/users", (req, res) =&gt; {
    res.send("Create new user");
});
</code></pre>
<h3>PUT Request</h3>
<p>Used to update existing data.</p>
<p>Example:</p>
<pre><code class="language-javascript">PUT /users/1
</code></pre>
<p>Express example:</p>
<pre><code class="language-javascript">app.put("/users/:id", (req, res) =&gt; {
    res.send("Update user");
});
</code></pre>
<h3>DELETE Request</h3>
<p>Used to remove data.</p>
<p>Example:</p>
<pre><code class="language-javascript">DELETE /users/1
</code></pre>
<p>Express example:</p>
<pre><code class="language-javascript">app.delete("/users/:id", (req, res) =&gt; {
    res.send("Delete user");
});
</code></pre>
<hr />
<h2>REST Route Design Principles</h2>
<p>REST APIs follow clean and predictable route naming conventions.</p>
<h3>Use Nouns Instead of Verbs</h3>
<p>Correct:</p>
<pre><code class="language-javascript">/users
/products
</code></pre>
<p>Incorrect:</p>
<pre><code class="language-javascript">/getUsers
/addProduct
</code></pre>
<p>The HTTP method already defines the action.</p>
<h3>Use Plural Resource Names</h3>
<p>Preferred:</p>
<pre><code class="language-javascript">/users
/posts
/orders
</code></pre>
<p>This makes APIs consistent and scalable.</p>
<h3>Keep URLs Clean and Predictable</h3>
<p>Good examples:</p>
<pre><code class="language-javascript">/users
/users/1
/users/1/posts
</code></pre>
<p>Avoid deeply nested complicated routes.</p>
<h3>Example REST API for Users Resource</h3>
<p>Here’s a clean RESTful design for users.</p>
<table>
<thead>
<tr>
<th>Action</th>
<th>Method</th>
<th>Route</th>
</tr>
</thead>
<tbody><tr>
<td>Get all users</td>
<td>GET</td>
<td><code>/users</code></td>
</tr>
<tr>
<td>Get single user</td>
<td>GET</td>
<td><code>/users/:id</code></td>
</tr>
<tr>
<td>Create user</td>
<td>POST</td>
<td><code>/users</code></td>
</tr>
<tr>
<td>Update user</td>
<td>PUT</td>
<td><code>/users/:id</code></td>
</tr>
<tr>
<td>Delete user</td>
<td>DELETE</td>
<td><code>/users/:id</code></td>
</tr>
</tbody></table>
<p>This structure becomes very intuitive once you follow REST principles consistently.</p>
<h3>REST Request-Response Lifecycle</h3>
<p>A REST API request typically follows this flow:</p>
<pre><code class="language-javascript">
Client Request
      ↓
Express Route
      ↓
Business Logic
      ↓
Database Operation
      ↓
JSON Response
</code></pre>
<hr />
<h2>Status Codes Basics</h2>
<p>HTTP status codes help clients understand the result of a request.</p>
<h3>Common Success Codes</h3>
<table>
<thead>
<tr>
<th>Status Code</th>
<th>Meaning</th>
</tr>
</thead>
<tbody><tr>
<td>200</td>
<td>Success</td>
</tr>
<tr>
<td>201</td>
<td>Resource Created</td>
</tr>
<tr>
<td>204</td>
<td>No Content</td>
</tr>
</tbody></table>
<p>Example:</p>
<pre><code class="language-javascript">res.status(201).json({
    message: "User created"
});
</code></pre>
<h3>Common Error Codes</h3>
<table>
<thead>
<tr>
<th>Status Code</th>
<th>Meaning</th>
</tr>
</thead>
<tbody><tr>
<td>400</td>
<td>Bad Request</td>
</tr>
<tr>
<td>401</td>
<td>Unauthorized</td>
</tr>
<tr>
<td>404</td>
<td>Not Found</td>
</tr>
<tr>
<td>500</td>
<td>Internal Server Error</td>
</tr>
</tbody></table>
<p>Example:</p>
<pre><code class="language-javascript">res.status(404).json({
    message: "User not found"
});
</code></pre>
<h3>Returning JSON Responses</h3>
<p>REST APIs commonly return JSON data.</p>
<p>Example:</p>
<pre><code class="language-javascript">res.json({
    id: 1,
    name: "Rohit"
});
</code></pre>
<p>Typical response:</p>
<pre><code class="language-json">{
  "id": 1,
  "name": "Rohit"
}
</code></pre>
<hr />
<h2>Building a Simple REST API in Express</h2>
<p>Example:</p>
<pre><code class="language-javascript">
import express from 'express';

const app = express();

app.use(express.json());

let users = [];

app.get("/users", (req, res) =&gt; {
    res.json(users);
});

app.post("/users", (req, res) =&gt; {
    users.push(req.body);

    res.status(201).json({
        message: "User created"
    });
});

app.listen(3000);
</code></pre>
<p>This demonstrates basic REST principles in action.</p>
<hr />
<h2>Conclusion</h2>
<p>REST APIs provide a clean and standardized way for clients and servers to communicate.</p>
<p>By understanding:</p>
<ul>
<li><p>resources</p>
</li>
<li><p>HTTP methods</p>
</li>
<li><p>route design</p>
</li>
<li><p>status codes</p>
</li>
<li><p>request-response flow</p>
</li>
</ul>
<p>you can build scalable and maintainable backend applications using Express.js.</p>
<p>Once you follow REST principles consistently, your APIs become easier to understand, easier to document, and much easier to scale in real-world applications.</p>
]]></content:encoded></item><item><title><![CDATA[Sessions vs JWT vs Cookies: Understanding Authentication Approaches]]></title><description><![CDATA[Authentication is one of the most important parts of backend development.Whenever users log in to an application, the server needs a way to identify them in future requests.
This is where concepts lik]]></description><link>https://blog.rohitchornele.online/sessions-vs-jwt-vs-cookies-understanding-authentication-approaches</link><guid isPermaLink="true">https://blog.rohitchornele.online/sessions-vs-jwt-vs-cookies-understanding-authentication-approaches</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[JWT]]></category><category><![CDATA[cookies]]></category><category><![CDATA[Session]]></category><dc:creator><![CDATA[Rohit Chornele]]></dc:creator><pubDate>Sun, 10 May 2026 17:11:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6688fdd59dfed4afe8f5b269/c7c56484-216b-4017-93f2-204feaf1dacb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Authentication is one of the most important parts of backend development.<br />Whenever users log in to an application, the server needs a way to identify them in future requests.</p>
<p>This is where concepts like:</p>
<ul>
<li><p>Sessions</p>
</li>
<li><p>Cookies</p>
</li>
<li><p>JWT (JSON Web Tokens)</p>
</li>
</ul>
<p>come into play.</p>
<p>Many beginners confuse these terms because they are often used together.<br />In reality, they solve different parts of the authentication process.</p>
<p>In this article, we’ll understand how sessions, cookies, and JWTs work, the difference between stateful and stateless authentication, and when each approach should be used in real-world applications.</p>
<hr />
<h2>Why Authentication is Needed</h2>
<p>Imagine a user logs into a website.</p>
<p>After login, every future request should identify:</p>
<ul>
<li><p>who the user is</p>
</li>
<li><p>whether they are authenticated</p>
</li>
<li><p>what permissions they have</p>
</li>
</ul>
<p>But HTTP is stateless by default.</p>
<p>That means every request is treated as completely new.</p>
<p>Authentication systems solve this problem by storing or sending user identity information between requests.</p>
<hr />
<h2>What are Cookies?</h2>
<p>Cookies are small pieces of data stored in the browser.</p>
<p>The server sends cookies to the client, and the browser automatically sends them back with future requests.</p>
<p>Example response header:</p>
<pre><code class="language-javascript">Set-Cookie: sessionId=abc123
</code></pre>
<p>The browser stores it and sends it automatically:</p>
<pre><code class="language-javascript">Cookie: sessionId=abc123
</code></pre>
<p>Cookies themselves are <strong>not authentication systems</strong>.</p>
<p>They are simply a storage mechanism used to store:</p>
<ul>
<li><p>session IDs</p>
</li>
<li><p>JWT tokens</p>
</li>
<li><p>user preferences</p>
</li>
<li><p>tracking information</p>
</li>
</ul>
<hr />
<h2>What are Sessions?</h2>
<p>A session is a server-side authentication mechanism.</p>
<p>In session-based authentication:</p>
<ol>
<li><p>User logs in</p>
</li>
<li><p>Server creates a session</p>
</li>
<li><p>Session data is stored on the server</p>
</li>
<li><p>A session ID is sent to the browser through cookies</p>
</li>
<li><p>Browser sends the session ID with every request</p>
</li>
<li><p>Server verifies the session</p>
</li>
</ol>
<h3>Session Authentication Flow</h3>
<pre><code class="language-plaintext">
User Login
    ↓
Server Creates Session
    ↓
Session Stored in Database/Memory
    ↓
Session ID Sent in Cookie
    ↓
Browser Stores Cookie
    ↓
Browser Sends Cookie in Future Requests
    ↓
Server Verifies Session
</code></pre>
<h3>Example of Session-Based Authentication</h3>
<p>After login :</p>
<pre><code class="language-javascript">req.session.user = {
    id: user._id,
    email: user.email
};
</code></pre>
<p>The server stores this session data.</p>
<p>The client only stores the session ID.</p>
<hr />
<h2>What are JWT Tokens?</h2>
<p>JWT stands for JSON Web Token.</p>
<p>A JWT is a self-contained token that stores user information directly inside the token itself.</p>
<p>Unlike sessions, JWT authentication usually does not require storing session data on the server.</p>
<p>Example JWT structure:</p>
<pre><code class="language-javascript">HEADER.PAYLOAD.SIGNATURE
</code></pre>
<p>Example payload:</p>
<pre><code class="language-javascript">{
  "id": "123",
  "email": "user@example.com"
}
</code></pre>
<p>The token is signed by the server to prevent tampering.</p>
<h3>JWT Authentication Flow</h3>
<pre><code class="language-plaintext">
User Login
    ↓
Server Creates JWT
    ↓
JWT Sent to Client
    ↓
Client Stores Token
    ↓
Client Sends JWT in Requests
    ↓
Server Verifies JWT Signature
    ↓
Request Authorized
</code></pre>
<h3>Example JWT Authentication</h3>
<p>Generating token:</p>
<pre><code class="language-javascript">const token = jwt.sign(
    {
        id: user._id
    },
    process.env.JWT_SECRET,
    {
        expiresIn: "7d"
    }
);
</code></pre>
<p>Sending token:</p>
<pre><code class="language-javascript">
res.json({
    token
});
</code></pre>
<p>Client sends token in headers:</p>
<pre><code class="language-javascript">Authorization: Bearer jwt_token_here
</code></pre>
<hr />
<h2>Stateful vs Stateless Authentication</h2>
<p>This is the biggest conceptual difference.</p>
<h3>Stateful Authentication</h3>
<p>Sessions are stateful.</p>
<p>The server stores authentication data.</p>
<p>Example:</p>
<pre><code class="language-javascript">
Server Memory / Database
    ↓
Session Data Stored
</code></pre>
<p>The server must remember every logged-in user.</p>
<h3>Stateless Authentication</h3>
<p>JWT is stateless.</p>
<p>The server does not store user login state.</p>
<p>The token itself contains the required information.</p>
<p>Example:</p>
<pre><code class="language-javascript">
Client Holds Token
    ↓
Server Only Verifies Signature
</code></pre>
<p>This makes JWT systems easier to scale.</p>
<h3>Sessions vs JWT Authentication</h3>
<p>Here’s the core difference.</p>
<table>
<thead>
<tr>
<th>Feature</th>
<th>Sessions</th>
<th>JWT</th>
</tr>
</thead>
<tbody><tr>
<td>Storage</td>
<td>Server-side</td>
<td>Client-side</td>
</tr>
<tr>
<td>Authentication Type</td>
<td>Stateful</td>
<td>Stateless</td>
</tr>
<tr>
<td>Scalability</td>
<td>Harder at large scale</td>
<td>Easier to scale</td>
</tr>
<tr>
<td>Token Size</td>
<td>Small session ID</td>
<td>Larger token</td>
</tr>
<tr>
<td>Server Memory Usage</td>
<td>Higher</td>
<td>Lower</td>
</tr>
<tr>
<td>Logout Handling</td>
<td>Easy</td>
<td>Slightly harder</td>
</tr>
<tr>
<td>Token Revocation</td>
<td>Easy</td>
<td>More complex</td>
</tr>
<tr>
<td>Automatic Browser Support</td>
<td>Yes via cookies</td>
<td>Usually manual</td>
</tr>
<tr>
<td>Mobile/API Friendly</td>
<td>Less ideal</td>
<td>Excellent</td>
</tr>
<tr>
<td>Best For</td>
<td>Traditional web apps</td>
<td>APIs &amp; modern apps</td>
</tr>
</tbody></table>
<h3>How Cookies Work with Sessions</h3>
<p>Sessions usually depend on cookies.</p>
<p>Example:</p>
<pre><code class="language-javascript">Cookie:
sessionId=abc123
</code></pre>
<p>The cookie stores only the session ID.</p>
<p>The actual user data remains on the server.</p>
<h3>How Cookies Work with JWT</h3>
<p>JWTs can also be stored inside cookies.</p>
<p>Example :</p>
<pre><code class="language-javascript">Cookie:
token=jwt_token_here
</code></pre>
<p>Or stored in:</p>
<ul>
<li><p>localStorage</p>
</li>
<li><p>sessionStorage</p>
</li>
<li><p>memory</p>
</li>
</ul>
<hr />
<h2>When to Use What</h2>
<h3>Session-Based Authentication</h3>
<p>Sessions are great for:</p>
<ul>
<li><p>traditional server-rendered websites</p>
</li>
<li><p>admin panels</p>
</li>
<li><p>applications with tight server control</p>
</li>
<li><p>systems requiring easy logout handling</p>
</li>
</ul>
<p><strong>Examples</strong>:</p>
<ul>
<li><p>banking portals</p>
</li>
<li><p>dashboards</p>
</li>
<li><p>CMS systems</p>
</li>
</ul>
<p><strong>Advantages</strong>:</p>
<ul>
<li><p>easy invalidation</p>
</li>
<li><p>secure server-controlled sessions</p>
</li>
<li><p>simpler browser integration</p>
</li>
</ul>
<h3>JWT Authentication</h3>
<p>JWT works best for:</p>
<ul>
<li><p>REST APIs</p>
</li>
<li><p>mobile apps</p>
</li>
<li><p>microservices</p>
</li>
<li><p>distributed systems</p>
</li>
<li><p>frontend-backend separated architectures</p>
</li>
</ul>
<p>Examples:</p>
<ul>
<li><p>React frontend + Node backend</p>
</li>
<li><p>mobile applications</p>
</li>
<li><p>third-party API authentication</p>
</li>
</ul>
<p>Advantages:</p>
<ul>
<li><p>scalable</p>
</li>
<li><p>lightweight server load</p>
</li>
<li><p>cross-platform friendly</p>
</li>
</ul>
<hr />
<h2>Conclusion</h2>
<p>Sessions, cookies, and JWTs are all important parts of authentication systems, but they serve different purposes.</p>
<ul>
<li><p>Cookies are browser storage mechanisms</p>
</li>
<li><p>Sessions store authentication state on the server</p>
</li>
<li><p>JWT stores authentication data inside signed tokens</p>
</li>
</ul>
<p>The biggest difference comes down to:</p>
<ul>
<li><p>stateful authentication (sessions)</p>
</li>
<li><p>stateless authentication (JWT)</p>
</li>
</ul>
<p>Neither approach is universally better.</p>
<p>Choosing the right authentication method depends on your application architecture, scalability needs, and development style.</p>
<p>Understanding these concepts clearly is essential for building secure and scalable backend applications.</p>
]]></content:encoded></item><item><title><![CDATA[What is Middleware in Express and How It Works]]></title><description><![CDATA[When building applications with Express.js, one of the most important concepts you’ll encounter is middleware.Middleware is what makes Express powerful, flexible, and easy to scale.
Whether it’s loggi]]></description><link>https://blog.rohitchornele.online/what-is-middleware-in-express-and-how-it-works</link><guid isPermaLink="true">https://blog.rohitchornele.online/what-is-middleware-in-express-and-how-it-works</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[Express]]></category><category><![CDATA[Middleware]]></category><dc:creator><![CDATA[Rohit Chornele]]></dc:creator><pubDate>Sun, 10 May 2026 16:59:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6688fdd59dfed4afe8f5b269/6f5b5531-dce7-41ac-a18e-2725ab322785.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When building applications with Express.js, one of the most important concepts you’ll encounter is <strong>middleware</strong>.<br />Middleware is what makes Express powerful, flexible, and easy to scale.</p>
<p>Whether it’s logging requests, checking authentication, validating input, or handling errors, middleware sits in the middle of the request-response cycle and controls how requests move through your application.</p>
<p>In this article, we’ll understand what middleware is, how it works internally, different types of middleware, and why it plays such a critical role in Express applications.</p>
<hr />
<h2>What is Middleware in Express?</h2>
<p>Middleware in Express is simply a <strong>function that runs between receiving a request and sending a response</strong>.</p>
<p>It gets access to:</p>
<ul>
<li><p><code>req</code> → the incoming request</p>
</li>
<li><p><code>res</code> → the response object</p>
</li>
<li><p><code>next()</code> → a function that passes control to the next middleware</p>
</li>
</ul>
<p>Basic syntax:</p>
<pre><code class="language-javascript">const middleware = (req, res, next) =&gt; {
    console.log("Middleware executed");

    next();
};
</code></pre>
<p>Middleware acts like a <strong>checkpoint</strong> in the request lifecycle.</p>
<p>Instead of sending every request directly to the route handler, Express allows middleware to inspect, modify, block, or process requests before they reach the final response.</p>
<hr />
<h2>Middleware in the Request Lifecycle</h2>
<p>Here’s how a request typically flows in Express:</p>
<pre><code class="language-plaintext">
Client Request
      ↓
Middleware 1
      ↓
Middleware 2
      ↓
Middleware 3
      ↓
Route Handler
      ↓
Response Sent
</code></pre>
<p>Think of middleware as workers standing in a pipeline.</p>
<p>Each worker performs a task and then either:</p>
<ul>
<li><p>passes the request forward using <code>next()</code></p>
</li>
<li><p>stops the request and sends a response</p>
</li>
</ul>
<hr />
<h2>Middleware Execution Flow</h2>
<p>A middleware chain works sequentially.</p>
<p>Example:</p>
<pre><code class="language-javascript">
app.use((req, res, next) =&gt; {
    console.log("First middleware");
    next();
});

app.use((req, res, next) =&gt; {
    console.log("Second middleware");
    next();
});

app.get("/", (req, res) =&gt; {
    res.send("Home Route");
});
</code></pre>
<p>When a request hits <code>/</code>, the output becomes:</p>
<pre><code class="language-plaintext">First middleware
Second middleware
</code></pre>
<p>Then the route handler sends the final response.</p>
<hr />
<h2>Role of <code>next()</code> Function</h2>
<p>The <code>next()</code> function is extremely important in Express middleware.</p>
<p>It tells Express:</p>
<blockquote>
<p>“Move to the next middleware or route handler.”</p>
</blockquote>
<p>Example:</p>
<pre><code class="language-javascript">const logger = (req, res, next) =&gt; {
    console.log(req.method, req.url);

    next();
};
</code></pre>
<p>Without calling <code>next()</code>, the request gets stuck and never reaches the next step.</p>
<p>Example of a blocked request:</p>
<pre><code class="language-javascript">app.use((req, res, next) =&gt; {
    console.log("Request received");
});
</code></pre>
<p>Since <code>next()</code> is missing and no response is sent, the browser keeps loading forever.</p>
<hr />
<h2>Types of Middleware in Express</h2>
<p>Express supports multiple types of middleware.</p>
<h3>1. Application-Level Middleware</h3>
<p>Application-level middleware is attached directly to the Express app using:</p>
<pre><code class="language-javascript">app.use()
</code></pre>
<p>Example:</p>
<pre><code class="language-javascript">app.use((req, res, next) =&gt; {
    console.log("Application middleware");
    next();
});
</code></pre>
<p>This middleware runs for every request unless restricted to a specific path.</p>
<p>Example with path:</p>
<pre><code class="language-javascript">app.use("/admin", (req, res, next) =&gt; {
    console.log("Admin middleware");
    next();
});
</code></pre>
<p>Now it only runs for routes starting with /admin.</p>
<h3>2. Router-Level Middleware</h3>
<p>Router-level middleware works specifically with Express routers.</p>
<p>Example:</p>
<pre><code class="language-javascript">
const router = express.Router();

router.use((req, res, next) =&gt; {
    console.log("Router middleware");
    next();
});
</code></pre>
<p>This middleware only affects routes inside that router.</p>
<p>Useful for:</p>
<ul>
<li><p>admin panels</p>
</li>
<li><p>API modules</p>
</li>
<li><p>authentication-protected sections</p>
</li>
</ul>
<h3>3. Built-in Middleware</h3>
<p>Express already provides some middleware functions.</p>
<p>Example:</p>
<ul>
<li><strong>JSON Middleware</strong></li>
</ul>
<pre><code class="language-javascript">app.use(express.json());
</code></pre>
<p>This parses incoming JSON request bodies.</p>
<p>Without it:</p>
<pre><code class="language-javascript">req.body
</code></pre>
<p>would be <code>undefined</code>.</p>
<ul>
<li><strong>Static File Middleware</strong></li>
</ul>
<pre><code class="language-javascript">app.use(express.static("public"));
</code></pre>
<p>This serves static files like:</p>
<ul>
<li><p>images</p>
</li>
<li><p>CSS</p>
</li>
<li><p>JavaScript files</p>
</li>
</ul>
<hr />
<h2>Execution Order of Middleware</h2>
<p>Middleware executes in the exact order it is defined.</p>
<p>Example :</p>
<pre><code class="language-javascript">
app.use((req, res, next) =&gt; {
    console.log("Middleware 1");
    next();
});

app.use((req, res, next) =&gt; {
    console.log("Middleware 2");
    next();
});
</code></pre>
<p>Output:</p>
<pre><code class="language-plaintext">Middleware 1
Middleware 2
</code></pre>
<p>If the order changes, behavior changes too.</p>
<p>This is extremely important for things like:</p>
<ul>
<li><p>authentication</p>
</li>
<li><p>body parsing</p>
</li>
<li><p>logging</p>
</li>
<li><p>validation</p>
</li>
</ul>
<p>For example, body parsing middleware should run before validation middleware.</p>
<hr />
<h2>Real-World Middleware Examples</h2>
<p>Middleware becomes powerful when used for common backend tasks.</p>
<h3>Logging Middleware</h3>
<p>Used to log request details.</p>
<p>Example:</p>
<pre><code class="language-javascript">
app.use((req, res, next) =&gt; {
    console.log(`\({req.method} \){req.url}`);
    next();
});
</code></pre>
<p>Output:</p>
<pre><code class="language-javascript">GET /users
POST /login
</code></pre>
<p>This helps in debugging and monitoring traffic.</p>
<h3>Authentication Middleware</h3>
<p>Checks whether a user is authenticated.</p>
<p>Example :</p>
<pre><code class="language-javascript">
const authMiddleware = (req, res, next) =&gt; {
    const token = req.headers.authorization;

    if (!token) {
        return res.status(401).json({
            message: "Unauthorized"
        });
    }

    next();
};
</code></pre>
<p><strong>Protected route:</strong></p>
<pre><code class="language-javascript">
app.get("/profile", authMiddleware, (req, res) =&gt; {
    res.send("Protected Profile");
});
</code></pre>
<h3>Request Validation Middleware</h3>
<p>Validates incoming request data before processing.</p>
<p>Example:</p>
<pre><code class="language-javascript">const validateUser = (req, res, next) =&gt; {
    const { name, email } = req.body;

    if (!name || !email) {
        return res.status(400).json({
            message: "All fields are required"
        });
    }

    next();
};
</code></pre>
<p><strong>Route usage:</strong></p>
<pre><code class="language-javascript">app.post("/users", validateUser, (req, res) =&gt; {
    res.send("User created");
});
</code></pre>
<hr />
<h2>Why Middleware is So Important</h2>
<p>Middleware is the backbone of Express applications.</p>
<p>It allows developers to:</p>
<ul>
<li><p>separate logic cleanly</p>
</li>
<li><p>reuse functionality</p>
</li>
<li><p>create scalable APIs</p>
</li>
<li><p>control request flow efficiently</p>
</li>
</ul>
<p>Almost every major backend feature in Express is implemented using middleware.</p>
<p>Examples include:</p>
<ul>
<li><p>authentication</p>
</li>
<li><p>file uploads</p>
</li>
<li><p>request parsing</p>
</li>
<li><p>CORS handling</p>
</li>
<li><p>logging</p>
</li>
<li><p>rate limiting</p>
</li>
<li><p>error handling</p>
</li>
</ul>
<hr />
<h2>Conclusion</h2>
<p>Middleware is one of the most powerful concepts in Express.js.</p>
<p>It acts as a bridge between the incoming request and the final response, allowing you to process requests step by step.</p>
<p>By understanding:</p>
<ul>
<li><p>how middleware works</p>
</li>
<li><p>execution order</p>
</li>
<li><p>the role of <code>next()</code></p>
</li>
<li><p>different middleware types</p>
</li>
</ul>
<p>you gain much better control over how your Express applications behave.</p>
<p>As your applications grow, middleware becomes essential for writing clean, organized, and maintainable backend code.</p>
]]></content:encoded></item><item><title><![CDATA[URL Parameters vs Query Strings in Express.js]]></title><description><![CDATA[When building APIs or web applications with Express.js, you’ll frequently work with dynamic URLs. Sometimes you need to identify a specific resource like a user or product, and other times you need to]]></description><link>https://blog.rohitchornele.online/url-parameters-vs-query-strings-in-express-js</link><guid isPermaLink="true">https://blog.rohitchornele.online/url-parameters-vs-query-strings-in-express-js</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[query string]]></category><category><![CDATA[URL Parameters]]></category><category><![CDATA[Node.js]]></category><dc:creator><![CDATA[Rohit Chornele]]></dc:creator><pubDate>Sun, 10 May 2026 16:40:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6688fdd59dfed4afe8f5b269/b20abfe6-90fe-4a43-82da-5f5e8a7b557d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When building APIs or web applications with Express.js, you’ll frequently work with dynamic URLs. Sometimes you need to identify a specific resource like a user or product, and other times you need to filter or modify data such as searching, sorting, or pagination.</p>
<p>This is where URL parameters and query strings come into play.</p>
<p>At first, both may look similar because they pass data through the URL, but they serve completely different purposes. Understanding when to use each one is important for designing clean and professional APIs.</p>
<p>In this article, we’ll understand the difference between URL parameters and query strings in a simple and practical way using Express.js examples.</p>
<hr />
<h2>What URL Parameters Are ?</h2>
<p>URL parameters, also called route parameters, are dynamic values written directly inside the URL path.</p>
<p>They are mainly used to identify a specific resource.</p>
<p>For example:</p>
<pre><code class="language-plaintext">/users/25
</code></pre>
<p>Here:</p>
<ul>
<li><p><code>users</code> represents the route  </p>
</li>
<li><p><code>25</code> represents a specific user ID</p>
</li>
</ul>
<p>In this case, <code>25</code> is a URL parameter.</p>
<p>Think of URL parameters as identifiers.</p>
<p>Examples:</p>
<ul>
<li><p>user ID</p>
</li>
<li><p>product ID</p>
</li>
<li><p>blog slug</p>
</li>
<li><p>order ID</p>
</li>
</ul>
<p>Example routes:</p>
<pre><code class="language-javascript">
/products/101
/blog/react-hooks-guide
/orders/9001
</code></pre>
<p>Each URL points to one specific resource.</p>
<h3>Accessing params in Express</h3>
<p>In Express, route parameters are accessed using:</p>
<pre><code class="language-javascript">req.params
</code></pre>
<p>Example:</p>
<pre><code class="language-javascript">
import express from "express";

const app = express();

app.get("/users/:id", (req, res) =&gt; {

  const userId = req.params.id;

  res.send(`User ID is ${userId}`);

});

app.listen(3000);
</code></pre>
<p>If the user visits:</p>
<pre><code class="language-plaintext">http://localhost:3000/users/25
</code></pre>
<p>Response:</p>
<pre><code class="language-javascript">User ID is 25
</code></pre>
<p>The <code>:id</code> part is called a route parameter placeholder.</p>
<p>Express automatically extracts the value and stores it inside <code>req.params</code>.</p>
<p>You can also use multiple parameters:</p>
<pre><code class="language-javascript">app.get("/users/:userId/posts/:postId", (req, res) =&gt; {

  res.json(req.params);

});
</code></pre>
<p>URL:</p>
<pre><code class="language-javascript">/users/25/posts/100
</code></pre>
<p>Response:</p>
<pre><code class="language-json">{
  "userId": "25",
  "postId": "100"
}
</code></pre>
<hr />
<h2>What query parameters are</h2>
<p>Query parameters, also called query strings, are extra values added after a <code>?</code> in the URL.</p>
<p>They are usually used for:</p>
<ul>
<li><p>filtering</p>
</li>
<li><p>sorting</p>
</li>
<li><p>searching</p>
</li>
<li><p>pagination</p>
</li>
<li><p>modifying results</p>
</li>
</ul>
<p>Example:</p>
<pre><code class="language-javascript">/products?category=mobile
</code></pre>
<p>Here:</p>
<ul>
<li><p><code>/products</code> is the main route</p>
</li>
<li><p><code>category=mobile</code> is a query parameter</p>
</li>
</ul>
<p>Unlike route parameters, query strings do not identify a specific resource.</p>
<p>Instead, they modify the response.</p>
<p>Think of query parameters as filters or modifiers.</p>
<h3>Accessing query strings in Express</h3>
<p>In Express, query parameters are accessed using:</p>
<pre><code class="language-javascript">req.query
</code></pre>
<p>Example:</p>
<pre><code class="language-javascript">
import express from "express";

const app = express();

app.get("/products", (req, res) =&gt; {

  const category = req.query.category;

  res.send(`Category is ${category}`);

});

app.listen(3000);
</code></pre>
<p>URL:</p>
<pre><code class="language-plaintext">http://localhost:3000/products?category=mobile
</code></pre>
<p>Response:</p>
<pre><code class="language-javascript">Category is mobile
</code></pre>
<p>Multiple query parameters can also be used:</p>
<pre><code class="language-javascript">/products?category=mobile&amp;sort=price&amp;page=2
</code></pre>
<p>Express converts them into an object:</p>
<pre><code class="language-json">{
  category: "mobile",
  sort: "price",
  page: "2"
}
</code></pre>
<hr />
<h2>Differences between them</h2>
<p>Although both are passed through the URL, their purpose is completely different.</p>
<table>
<thead>
<tr>
<th>Feature</th>
<th>URL Parameters</th>
<th>Query Parameters</th>
</tr>
</thead>
<tbody><tr>
<td>Purpose</td>
<td>Identify a specific resource</td>
<td>Filter or modify data</td>
</tr>
<tr>
<td>Position</td>
<td>Inside URL path</td>
<td>After <code>?</code></td>
</tr>
<tr>
<td>Required</td>
<td>Usually required</td>
<td>Usually optional</td>
</tr>
<tr>
<td>Example</td>
<td><code>/users/25</code></td>
<td><code>/users?age=25</code></td>
</tr>
<tr>
<td>Usage</td>
<td>IDs, slugs</td>
<td>search, filters, sorting</td>
</tr>
</tbody></table>
<h3>Understanding with practical examples</h3>
<h3>Example 1: User profile ID</h3>
<pre><code class="language-javascript">/users/25
</code></pre>
<p>Here:</p>
<ul>
<li><p><code>25</code> identifies a specific user</p>
</li>
<li><p>URL parameter should be used</p>
</li>
</ul>
<p>Express route:</p>
<pre><code class="language-javascript">
app.get("/users/:id", (req, res) =&gt; {

  const id = req.params.id;

  res.send(`Fetching user ${id}`);

});
</code></pre>
<h3>Example 2: Search filters</h3>
<pre><code class="language-javascript">/products?category=mobile&amp;brand=samsung
</code></pre>
<p>Here:</p>
<ul>
<li><p>we are filtering products</p>
</li>
<li><p>query strings should be used</p>
</li>
</ul>
<p>Express route:</p>
<pre><code class="language-javascript">app.get("/products", (req, res) =&gt; {

  const { category, brand } = req.query;

  res.json({
    category,
    brand
  });

});
</code></pre>
<h3>URL structure breakdown</h3>
<p>Example URL:</p>
<pre><code class="language-javascript">/users/25/orders?status=completed&amp;page=1
</code></pre>
<p>Breakdown:</p>
<pre><code class="language-javascript">/users           → route
25               → URL parameter
/orders          → nested route
status=completed → query parameter
page=1           → query parameter
</code></pre>
<p>This clearly shows how both params and query strings can exist together in the same URL.</p>
<hr />
<h2>When To Use Params vs Query</h2>
<p>A simple rule developers commonly follow:</p>
<h3>Use URL parameters when:</h3>
<ul>
<li><p>identifying a specific resource</p>
</li>
<li><p>fetching one item</p>
</li>
<li><p>route structure depends on value</p>
</li>
</ul>
<p>Examples:</p>
<ul>
<li><p><code>/users/10</code></p>
</li>
<li><p><code>/products/55</code></p>
</li>
<li><p><code>/posts/react-guide</code></p>
</li>
</ul>
<h3>Use query strings when:</h3>
<ul>
<li><p>filtering data</p>
</li>
<li><p>sorting results</p>
</li>
<li><p>searching</p>
</li>
<li><p>pagination</p>
</li>
<li><p>optional modifiers</p>
</li>
</ul>
<p>Examples:</p>
<ul>
<li><p><code>/products?category=laptop</code></p>
</li>
<li><p><code>/users?page=2</code></p>
</li>
<li><p><code>/search?keyword=nodejs</code></p>
</li>
</ul>
<h3>Params vs query comparison diagram</h3>
<pre><code class="language-javascript">
URL Parameter Example:
--------------------------------
/users/25
       ↑
    Specific Resource ID


Query Parameter Example:
--------------------------------
/users?age=25&amp;city=Delhi
      ↑
   Filters / Modifiers
</code></pre>
<hr />
<h2>Conclusion</h2>
<p>URL parameters and query strings may look similar, but they solve different problems in web applications. Route parameters are mainly used for identifying specific resources, while query strings are used for filtering, searching, sorting, or modifying results.</p>
<p>Understanding this difference helps you design cleaner APIs and makes your routes easier to understand and maintain. A good Express application uses both properly depending on the purpose of the request.</p>
<p>Once you become comfortable with params and query strings, building dynamic routes and flexible APIs in Express.js becomes much more intuitive.</p>
]]></content:encoded></item><item><title><![CDATA[Handling File Uploads in Express with Multer]]></title><description><![CDATA[File uploads are one of the most common features in backend applications. Whether users are uploading profile images, PDFs, resumes, or product photos, the server needs a proper way to receive and sto]]></description><link>https://blog.rohitchornele.online/handling-file-uploads-in-express-with-multer</link><guid isPermaLink="true">https://blog.rohitchornele.online/handling-file-uploads-in-express-with-multer</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Express]]></category><category><![CDATA[multer]]></category><category><![CDATA[File handling]]></category><category><![CDATA[File Upload]]></category><dc:creator><![CDATA[Rohit Chornele]]></dc:creator><pubDate>Sun, 10 May 2026 16:13:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6688fdd59dfed4afe8f5b269/c48a9140-633e-41f0-8a84-53dfcd4fc99c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>File uploads are one of the most common features in backend applications. Whether users are uploading profile images, PDFs, resumes, or product photos, the server needs a proper way to receive and store those files.</p>
<p>In Express applications, handling uploads is not as straightforward as handling normal JSON data. Files are sent differently by the browser, which is why we need specialized middleware like Multer.</p>
<p>In this article, we’ll understand how file uploads work in Express using Multer, how to upload single and multiple files, and how uploaded files are eventually served to users.</p>
<hr />
<h2>Why file uploads need middleware</h2>
<p>When we send normal form data, Express can easily read it using middleware like:</p>
<pre><code class="language-javascript">
app.use(express.json());
</code></pre>
<p>But file uploads work differently.</p>
<p>Files are usually sent using a format called:</p>
<pre><code class="language-plaintext">multipart/form-data
</code></pre>
<p>This format contains:</p>
<ul>
<li><p>file data</p>
</li>
<li><p>form fields</p>
</li>
<li><p>metadata</p>
</li>
</ul>
<p>Unlike JSON, Express cannot parse multipart data by default.</p>
<p>That’s why file upload middleware is required.</p>
<p>Without middleware:</p>
<ul>
<li><p><code>req.body</code> may work for text fields</p>
</li>
<li><p>uploaded files will not be processed correctly</p>
</li>
</ul>
<p>This is where Multer helps.</p>
<hr />
<h2>What Multer is ?</h2>
<p>Multer is a middleware for Express that handles <code>multipart/form-data</code>.</p>
<p>Its main job is to:</p>
<ul>
<li><p>receive uploaded files</p>
</li>
<li><p>process them</p>
</li>
<li><p>store them on the server</p>
</li>
<li><p>provide file information inside the request object</p>
</li>
</ul>
<p>Install Multer:</p>
<pre><code class="language-plaintext">
npm install multer
</code></pre>
<p>Basic Setup :</p>
<pre><code class="language-javascript">
import express from "express";
import multer from "multer";

const app = express();

const upload = multer({
  dest: "uploads/"
});
</code></pre>
<p>Here :</p>
<ul>
<li><p>Multer stores uploaded files inside the <code>uploads</code> folder</p>
</li>
<li><p>file information becomes available in the request</p>
</li>
</ul>
<hr />
<h2>Understanding the upload lifecycle</h2>
<p>Here’s what happens behind the scenes during a file upload:</p>
<pre><code class="language-javascript">Client Selects File
        ↓
Browser Sends multipart/form-data Request
        ↓
Multer Middleware Receives File
        ↓
Multer Processes File
        ↓
File Stored in uploads Folder
        ↓
Request Continues to Route Handler
</code></pre>
<p>Multer acts like a middle layer between the incoming request and your route handler.</p>
<hr />
<h2>Handling single file upload</h2>
<p>Single file uploads are commonly used for:</p>
<ul>
<li><p>profile pictures</p>
</li>
<li><p>thumbnails</p>
</li>
<li><p>resumes</p>
</li>
<li><p>documents</p>
</li>
</ul>
<p>Example:</p>
<pre><code class="language-javascript">
import express from "express";
import multer from "multer";

const app = express();

const upload = multer({
  dest: "uploads/"
});

app.post("/upload", upload.single("image"), (req, res) =&gt; {

  res.json({
    message: "File uploaded successfully",
    file: req.file
  });

});

app.listen(3000);
</code></pre>
<p>Important part:</p>
<pre><code class="language-javascript">
upload.single("image")
</code></pre>
<p>This means:</p>
<ul>
<li><p>only one file is expected</p>
</li>
<li><p>the input field name must be <code>image</code></p>
</li>
</ul>
<p>Example frontend form:</p>
<pre><code class="language-html">
&lt;form action="/upload" method="POST" enctype="multipart/form-data"&gt;

  &lt;input type="file" name="image" /&gt;

  &lt;button type="submit"&gt;
    Upload
  &lt;/button&gt;

&lt;/form&gt;
</code></pre>
<p>The <code>enctype="multipart/form-data"</code> is very important. Without it, files will not be sent properly.</p>
<p>After upload:</p>
<ul>
<li><p>file details are available inside <code>req.file</code></p>
</li>
<li><p>Multer automatically stores the file</p>
</li>
</ul>
<hr />
<h2>Handling multiple file uploads</h2>
<p>Sometimes users need to upload multiple files together.</p>
<p>Examples:</p>
<ul>
<li><p>product gallery images</p>
</li>
<li><p>project documents</p>
</li>
<li><p>media uploads</p>
</li>
</ul>
<p>Multer provides:</p>
<pre><code class="language-javascript">
upload.array()
</code></pre>
<p>Example:</p>
<pre><code class="language-javascript">
import express from "express";
import multer from "multer";

const app = express();

const upload = multer({
  dest: "uploads/"
});

app.post("/uploads", upload.array("images", 5), (req, res) =&gt; {

  res.json({
    message: "Files uploaded successfully",
    files: req.files
  });

});
</code></pre>
<p>Here:</p>
<pre><code class="language-javascript">
upload.array("images", 5)
</code></pre>
<p>means:</p>
<ul>
<li><p>field name is <code>images</code></p>
</li>
<li><p>maximum 5 files allowed</p>
</li>
</ul>
<p>Frontend example:</p>
<pre><code class="language-html">
&lt;form action="/uploads" method="POST" enctype="multipart/form-data"&gt;

  &lt;input type="file" name="images" multiple /&gt;

  &lt;button type="submit"&gt;
    Upload Files
  &lt;/button&gt;

&lt;/form&gt;
</code></pre>
<p>Uploaded file details are available in:</p>
<pre><code class="language-javascript">
req.files
</code></pre>
<hr />
<h2>Storage configuration basics</h2>
<p>By default, Multer generates random file names.</p>
<p>But in real applications, developers usually configure storage manually.</p>
<p>Example:</p>
<pre><code class="language-plaintext">const storage = multer.diskStorage({

  destination: (req, file, cb) =&gt; {
    cb(null, "uploads/");
  },

  filename: (req, file, cb) =&gt; {

    const uniqueName =
      Date.now() + "-" + file.originalname;

    cb(null, uniqueName);
  }

});

const upload = multer({ storage });
</code></pre>
<p>This configuration helps:</p>
<ul>
<li><p>organize uploaded files</p>
</li>
<li><p>avoid duplicate file names</p>
</li>
<li><p>generate readable file names</p>
</li>
</ul>
<p>Example generated file:</p>
<pre><code class="language-plaintext">174689223-profile.png
</code></pre>
<p>Minimal folder structure:</p>
<pre><code class="language-javascript">project/
│
├── uploads/
├── server.js
└── package.json
</code></pre>
<p>Keeping the structure simple makes uploads easier to understand for beginners.</p>
<hr />
<h2>Serving uploaded files</h2>
<p>Uploading files is only part of the process. Users also need access to those uploaded files.</p>
<p>Express provides static middleware for this.</p>
<p>Example:</p>
<pre><code class="language-javascript">app.use("/uploads", express.static("uploads"));
</code></pre>
<p>This line tells Express:</p>
<blockquote>
<p>“Everything inside the uploads folder can be accessed publicly.”</p>
</blockquote>
<p>Suppose the folder contains:</p>
<pre><code class="language-javascript">uploads/
└── profile.png
</code></pre>
<p>The file becomes accessible at:</p>
<pre><code class="language-plaintext">http://localhost:3000/uploads/profile.png
</code></pre>
<p>This URL can be used:</p>
<ul>
<li><p>inside <code>&lt;img&gt;</code> tags</p>
</li>
<li><p>in frontend applications</p>
</li>
<li><p>for downloads</p>
</li>
<li><p>in mobile apps</p>
</li>
</ul>
<p>Complete example:</p>
<pre><code class="language-javascript">
import express from "express";
import multer from "multer";

const app = express();

const storage = multer.diskStorage({

  destination: (req, file, cb) =&gt; {
    cb(null, "uploads/");
  },

  filename: (req, file, cb) =&gt; {

    const uniqueName =
      Date.now() + "-" + file.originalname;

    cb(null, uniqueName);
  }

});

const upload = multer({ storage });

app.use("/uploads", express.static("uploads"));

app.post("/upload", upload.single("image"), (req, res) =&gt; {

  const fileUrl =
    `\({req.protocol}://\){req.get("host")}/uploads/${req.file.filename}`;

  res.json({
    message: "Upload successful",
    url: fileUrl
  });

});

app.listen(3000);
</code></pre>
<h3>Multer middleware execution flow</h3>
<p>Here’s the complete execution flow:</p>
<pre><code class="language-plaintext">User Selects File
        ↓
Browser Sends multipart/form-data Request
        ↓
Multer Middleware Executes
        ↓
File Saved in uploads Folder
        ↓
req.file or req.files Created
        ↓
Route Handler Executes
        ↓
Response Sent to Client
</code></pre>
<p>Understanding this flow makes it much easier to debug upload-related issues in Express applications.</p>
<hr />
<h2>Conclusion</h2>
<p>File uploads may look simple from the frontend, but a lot happens behind the scenes on the server. Since Express cannot process multipart file data on its own, middleware like Multer becomes essential for handling uploads properly.</p>
<p>Once you understand how Multer receives files, stores them, and passes file information to route handlers, building features like profile image uploads, document systems, or media galleries becomes much easier. Starting with local storage is the best way to learn the complete upload flow before moving toward advanced solutions like cloud storage or CDN-based systems later.</p>
]]></content:encoded></item><item><title><![CDATA[Storing Uploaded Files and Serving Them in Express]]></title><description><![CDATA[File uploads are a common feature in modern web applications. Whether users are uploading profile pictures, documents, videos, or PDFs, the backend needs a proper system to store and serve those files]]></description><link>https://blog.rohitchornele.online/storing-uploaded-files-and-serving-them-in-express</link><guid isPermaLink="true">https://blog.rohitchornele.online/storing-uploaded-files-and-serving-them-in-express</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Express]]></category><category><![CDATA[upload]]></category><dc:creator><![CDATA[Rohit Chornele]]></dc:creator><pubDate>Sun, 10 May 2026 15:53:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6688fdd59dfed4afe8f5b269/6a9e5a7a-b5ce-4ce4-856f-bafb0c9978e8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>File uploads are a common feature in modern web applications. Whether users are uploading profile pictures, documents, videos, or PDFs, the backend needs a proper system to store and serve those files safely.</p>
<p>In Express applications, file handling usually involves two important parts:</p>
<ul>
<li><p>storing uploaded files</p>
</li>
<li><p>making those files accessible through URLs</p>
</li>
</ul>
<p>Let’s understand how this works behind the scenes.</p>
<hr />
<h2>Where uploaded files are stored</h2>
<p>When a user uploads a file, the backend receives it as binary data. Your server then decides where that file should be stored.</p>
<p>In most beginner-level Express applications, uploaded files are stored inside a folder on the server itself. This is commonly called local storage.</p>
<p>Example folder structure:</p>
<pre><code class="language-plaintext"> project/
 │
 ├── uploads/
 │   ├── image1.png
 │   ├── resume.pdf
 │   └── profile.jpg
 │
 ├── server.js
 └── package.json
</code></pre>
<p>The <code>uploads</code> folder contains all uploaded files.</p>
<p>Most developers use Multer middleware for handling file uploads in Express.</p>
<p>Example:</p>
<pre><code class="language-javascript">
import express from "express";
import multer from "multer";

const app = express();

const storage = multer.diskStorage({
  destination: (req, file, cb) =&gt; {
    cb(null, "uploads/");
  },

  filename: (req, file, cb) =&gt; {
    const uniqueName = Date.now() + "-" + file.originalname;
    cb(null, uniqueName);
  }
});

const upload = multer({ storage });

app.post("/upload", upload.single("image"), (req, res) =&gt; {

  res.json({
    message: "File uploaded successfully",
    file: req.file
  });

});

app.listen(3000);
</code></pre>
<p>In this example:</p>
<ul>
<li><p>files are stored inside the <code>uploads</code> folder</p>
</li>
<li><p>every file gets a unique name</p>
</li>
<li><p><code>req.file</code> contains uploaded file information</p>
</li>
</ul>
<p>Adding unique names is important because multiple users may upload files with the same name.</p>
<p>For example:</p>
<pre><code class="language-javascript">profile.png
</code></pre>
<p>Without unique naming, newer uploads may overwrite older files.</p>
<hr />
<h2>Local storage vs external storage concept</h2>
<p>Local storage works well for:</p>
<ul>
<li><p>small applications</p>
</li>
<li><p>learning projects</p>
</li>
<li><p>development environments</p>
</li>
</ul>
<p>But as applications grow, storing files directly on the server becomes difficult to manage.</p>
<p>That’s where external storage comes in.</p>
<p>Instead of storing files locally, the backend uploads files to cloud services such as:</p>
<ul>
<li><p>Amazon Web Services S3</p>
</li>
<li><p>Cloudinary</p>
</li>
<li><p>Firebase Storage</p>
</li>
<li><p>Google Cloud Storage</p>
</li>
</ul>
<p>The overall flow looks like this:</p>
<pre><code class="language-javascript">
  User Uploads File
          ↓
  Express Server Receives File
          ↓
  File Uploaded to Cloud Storage
          ↓
  Cloud Service Returns URL
          ↓
  URL Stored in Database
</code></pre>
<p>Here’s a simple comparison:</p>
<table>
<thead>
<tr>
<th>Feature</th>
<th>Local Storage</th>
<th>External Storage</th>
</tr>
</thead>
<tbody><tr>
<td>Easy to setup</td>
<td>✅ Yes</td>
<td>❌ More setup</td>
</tr>
<tr>
<td>Good for beginners</td>
<td>✅ Yes</td>
<td>❌ Slightly advanced</td>
</tr>
<tr>
<td>Scalable</td>
<td>❌ Limited</td>
<td>✅ Highly scalable</td>
</tr>
<tr>
<td>Backup handling</td>
<td>❌ Manual</td>
<td>✅ Managed by provider</td>
</tr>
<tr>
<td>Best for production</td>
<td>❌ Limited</td>
<td>✅ Yes</td>
</tr>
</tbody></table>
<p>For small apps, local storage is perfectly fine. But production-level applications usually prefer external storage because it is more scalable and reliable.</p>
<hr />
<h2>Serving static files in Express</h2>
<p>Uploading files is only half the process. Users also need a way to access those files in the browser.</p>
<p>Express provides built-in middleware for serving static files.</p>
<p>Example:</p>
<pre><code class="language-javascript">
app.use("/uploads", express.static("uploads"));
</code></pre>
<p>This line tells Express:</p>
<blockquote>
<p>“Everything inside the uploads folder can be accessed publicly.”</p>
</blockquote>
<p>Suppose your folder contains:</p>
<pre><code class="language-plaintext">
uploads/
└── photo.png
</code></pre>
<p>Now the file becomes accessible at:</p>
<pre><code class="language-plaintext">
http://localhost:3000/uploads/photo.png
</code></pre>
<p>This is called static file serving.</p>
<p>Static files are files that do not require backend processing before being sent to the client.</p>
<p>Examples include:</p>
<ul>
<li><p>images</p>
</li>
<li><p>videos</p>
</li>
<li><p>PDFs</p>
</li>
<li><p>CSS files</p>
</li>
<li><p>JavaScript files</p>
</li>
</ul>
<p>Express simply reads the file and sends it directly to the browser.</p>
<p>A complete example:</p>
<pre><code class="language-javascript">
import express from "express";
import multer from "multer";

const app = express();

const storage = multer.diskStorage({
  destination: (req, file, cb) =&gt; {
    cb(null, "uploads/");
  },

  filename: (req, file, cb) =&gt; {
    const uniqueName = Date.now() + "-" + file.originalname;
    cb(null, uniqueName);
  }
});

const upload = multer({ storage });

app.use("/uploads", express.static("uploads"));

app.post("/upload", upload.single("image"), (req, res) =&gt; {

  res.json({
    message: "File uploaded successfully",
    file: req.file
  });

});

app.listen(3000);
</code></pre>
<hr />
<h2>Accessing uploaded files via URL</h2>
<p>Once static serving is enabled, uploaded files can be accessed directly using URLs.</p>
<p>For example:</p>
<pre><code class="language-plaintext">
http://localhost:3000/uploads/image.png
</code></pre>
<p>This URL can be used:</p>
<ul>
<li><p>inside <code>&lt;img&gt;</code> tags</p>
</li>
<li><p>for file downloads</p>
</li>
<li><p>in frontend applications</p>
</li>
<li><p>inside mobile apps</p>
</li>
</ul>
<p>Developers often generate file URLs dynamically after upload.</p>
<p>Example:</p>
<pre><code class="language-javascript">
app.post("/upload", upload.single("image"), (req, res) =&gt; {

  const fileUrl =
    `\({req.protocol}://\){req.get("host")}/uploads/${req.file.filename}`;

  res.json({
    message: "Upload successful",
    url: fileUrl
  });

});
</code></pre>
<p><strong>Response</strong>:</p>
<pre><code class="language-json">
{
  "message": "Upload successful",
  "url": "http://localhost:3000/uploads/1746892-image.png"
}
</code></pre>
<p>Now the frontend can directly display the uploaded image:</p>
<pre><code class="language-html">
&lt;img src="FILE_URL" /&gt;
</code></pre>
<p>This is how profile pictures, product images, and downloadable documents are usually displayed in web applications.</p>
<hr />
<h2>Security considerations for uploads</h2>
<p>File uploads can become dangerous if not handled properly. A malicious user may try to upload harmful files or overload the server.</p>
<p>That’s why upload security is extremely important.</p>
<h3>Restrict file types</h3>
<p>Only allow specific file formats.</p>
<p>Example:</p>
<pre><code class="language-javascript">
const fileFilter = (req, file, cb) =&gt; {

  const allowedTypes = ["image/png", "image/jpeg"];

  if (allowedTypes.includes(file.mimetype)) {
    cb(null, true);
  } else {
    cb(new Error("Invalid file type"), false);
  }

};

const upload = multer({
  storage,
  fileFilter
});
</code></pre>
<p>This prevents unsupported or dangerous file types from being uploaded.</p>
<h3>Limit file size</h3>
<p>Large files can slow down or crash the server.</p>
<p>Example:</p>
<pre><code class="language-javascript">
const upload = multer({
  storage,
  limits: {
    fileSize: 5 * 1024 * 1024
  }
});
</code></pre>
<p>This limits uploads to 5MB.</p>
<h3>Never trust original file names</h3>
<p>Users can upload suspicious file names like:</p>
<pre><code class="language-html">
../../../hack.js
</code></pre>
<p>Always rename files before storing them.</p>
<h3>Keep sensitive files private</h3>
<p>Not every uploaded file should be publicly accessible.</p>
<p>Examples:</p>
<ul>
<li><p>identity documents</p>
</li>
<li><p>invoices</p>
</li>
<li><p>medical reports</p>
</li>
</ul>
<p>Such files should:</p>
<ul>
<li><p>stay outside public folders</p>
</li>
<li><p>require authentication before access</p>
</li>
</ul>
<h3>Organize uploads properly</h3>
<p>A clean folder structure helps maintain files easily.</p>
<p>Example:</p>
<pre><code class="language-plaintext">
uploads/
│
├── profiles/
├── products/
└── documents/
</code></pre>
<p>This makes file management much easier as the application grows.</p>
<h2>Conclucsion</h2>
<p>Handling file uploads in Express is not just about saving files to a folder. A proper upload system should also organize files correctly, make them accessible through URLs, and protect the server from unsafe uploads.</p>
<p>For small projects or learning purposes, local storage is usually enough and very easy to implement. But as applications grow and start handling large numbers of users or media files, external storage solutions become a much better option because they offer better scalability, reliability, and performance.</p>
<p>Once you understand how uploading, storage, static serving, and security work together, building features like profile image uploads, document sharing systems, galleries, or media platforms becomes much more manageable and professional.</p>
]]></content:encoded></item><item><title><![CDATA[Creating Routes and Handling Requests with Express]]></title><description><![CDATA[Once developers start building backend applications with Node.js, one of the first things they realize is that creating servers using Node’s built-in HTTP module can become repetitive very quickly.
Ev]]></description><link>https://blog.rohitchornele.online/creating-routes-and-handling-requests-with-express</link><guid isPermaLink="true">https://blog.rohitchornele.online/creating-routes-and-handling-requests-with-express</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Express]]></category><category><![CDATA[routes]]></category><category><![CDATA[Requests]]></category><dc:creator><![CDATA[Rohit Chornele]]></dc:creator><pubDate>Sun, 10 May 2026 14:57:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6688fdd59dfed4afe8f5b269/5c9bf456-438d-4e05-8cb6-5ac5830bee56.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Once developers start building backend applications with Node.js, one of the first things they realize is that creating servers using Node’s built-in HTTP module can become repetitive very quickly.</p>
<p>Even simple tasks like:</p>
<ul>
<li><p>handling routes</p>
</li>
<li><p>managing requests</p>
</li>
<li><p>sending responses</p>
</li>
<li><p>parsing data</p>
</li>
</ul>
<p>require a lot of manual code.</p>
<p>That’s exactly why:</p>
<p>Express.js</p>
<p>became so popular.</p>
<p>Express is a lightweight web framework built on top of Node.js that makes backend development much simpler, cleaner, and faster.</p>
<p>In this article, we’ll understand what Express.js is, why developers use it, and how to create routes and handle requests using Express.</p>
<hr />
<h2>What Express.js Is ?</h2>
<p>Express.js is a minimal and flexible web framework for Node.js.</p>
<p>It helps developers build:</p>
<ul>
<li><p>APIs</p>
</li>
<li><p>web servers</p>
</li>
<li><p>backend applications</p>
</li>
<li><p>REST services</p>
</li>
</ul>
<p>without writing repetitive low-level server code again and again.</p>
<p>Think of Node.js as the engine of a car.</p>
<p>Express.js is like the steering wheel, dashboard, and controls that make driving easier.</p>
<p>Node.js provides the core functionality, while Express provides a cleaner and more developer-friendly way to work with servers and routes.</p>
<hr />
<h2>Why Express Simplifies Node.js Development</h2>
<p>To understand why Express became popular, let’s compare it with a raw Node.js HTTP server.</p>
<h3>Raw Node.js HTTP Server</h3>
<p>Here’s a simple server using Node.js only :</p>
<pre><code class="language-javascript">import http from 'http';

const server = http.createServer((req, res) =&gt; {

  if (req.url === "/") {
    res.send("Home Page");
  }

  else if (req.url === "/about") {
    res.send("About Page");
  }

});

server.listen(3000);
</code></pre>
<p>This works, but as the application grows:</p>
<ul>
<li><p>routing becomes messy</p>
</li>
<li><p>request handling becomes repetitive</p>
</li>
<li><p>middleware becomes difficult</p>
</li>
<li><p>code organization suffers</p>
</li>
</ul>
<p>Now compare that with Express.</p>
<h3>Express Server Example</h3>
<pre><code class="language-javascript">
import express from 'express';

const app = express();

app.get("/", (req, res) =&gt; {
  res.send("Home Page");
});

app.get("/about", (req, res) =&gt; {
  res.send("About Page");
});

app.listen(3000);
</code></pre>
<p>The difference is immediately noticeable.</p>
<p>The code is:</p>
<ul>
<li><p>shorter</p>
</li>
<li><p>cleaner</p>
</li>
<li><p>easier to read</p>
</li>
<li><p>easier to scale</p>
</li>
</ul>
<p>That simplicity is one of the biggest reasons developers love Express.</p>
<hr />
<h2>Creating First Express Server</h2>
<p>Now let’s create a basic Express server step-by-step.</p>
<p>Create a file called:</p>
<pre><code class="language-plaintext">app.js
</code></pre>
<p>Then add this code:</p>
<pre><code class="language-javascript">
import express from 'express';

const app = express();

app.listen(3000, () =&gt; {
  console.log("Server running on port 3000");
});
</code></pre>
<p>Here’s what’s happening:</p>
<ul>
<li><p><code>express()</code> creates an Express application</p>
</li>
<li><p><code>app.listen()</code> starts the server</p>
</li>
<li><p>port <code>3000</code> becomes active</p>
</li>
</ul>
<p>Run the file using:</p>
<pre><code class="language-plaintext">
node app.js
</code></pre>
<hr />
<h2>Understanding Routes in Express</h2>
<p>A route is simply a path that the server responds to.</p>
<p>For example:</p>
<ul>
<li><p><code>/</code></p>
</li>
<li><p><code>/about</code></p>
</li>
<li><p><code>/contact</code></p>
</li>
</ul>
<p>Different routes usually return different data or pages.</p>
<p>Express makes routing extremely simple using methods like:</p>
<ul>
<li><p><code>app.get()</code></p>
</li>
<li><p><a href="http://app.post"><code>app.post</code></a><code>()</code></p>
</li>
<li><p><code>app.put()</code></p>
</li>
<li><p><code>app.delete()</code></p>
</li>
</ul>
<p>Each route contains:</p>
<ol>
<li><p>a URL path</p>
</li>
<li><p>a request handler function</p>
</li>
</ol>
<hr />
<h2>Handling GET Requests</h2>
<p>GET requests are mainly used to retrieve data from the server.</p>
<p>Here’s a simple example:</p>
<pre><code class="language-javascript">import express from 'express';

const app = express();

app.get("/", (req, res) =&gt; {
  res.send("Welcome to Express");
});

app.get("/about", (req, res) =&gt; {
  res.send("About Page");
});

app.listen(3000);
</code></pre>
<p>Now:</p>
<ul>
<li><p>visiting <code>/</code> returns <code>"Welcome to Express"</code></p>
</li>
<li><p>visiting <code>/about</code> returns <code>"About Page"</code></p>
</li>
</ul>
<p>Express automatically checks the route and runs the correct handler.</p>
<h3>Request → Route Handler → Response Flow</h3>
<pre><code class="language-javascript">
  Browser Request
         ↓
  Express Route Matches URL
         ↓
  Route Handler Executes
         ↓
  Response Sent Back
</code></pre>
<p>This request-response cycle is the foundation of almost every backend application.</p>
<hr />
<h2>Handling POST Requests</h2>
<p>POST requests are used when the client wants to send data to the server.</p>
<p>Examples include:</p>
<ul>
<li><p>login forms</p>
</li>
<li><p>registration forms</p>
</li>
<li><p>creating new records</p>
</li>
<li><p>submitting data</p>
</li>
</ul>
<p>Here’s a basic POST route:</p>
<pre><code class="language-javascript">
app.post("/login", (req, res) =&gt; {
  res.send("Login Successful");
});
</code></pre>
<p>When a POST request hits <code>/login</code>, Express executes the route handler and sends a response back.</p>
<p>Even though this example is simple, the same concept is used in real-world authentication systems and APIs.</p>
<hr />
<h2>Sending Responses in Express</h2>
<p>Express provides several ways to send responses.</p>
<p>The most common one is:</p>
<pre><code class="language-plaintext">res.send()
</code></pre>
<p>It can send:</p>
<ul>
<li><p>text</p>
</li>
<li><p>HTML</p>
</li>
<li><p>JSON</p>
</li>
<li><p>objects</p>
</li>
</ul>
<p>Example:</p>
<pre><code class="language-javascript">res.send("Hello World");
</code></pre>
<p>You can also send JSON responses:</p>
<pre><code class="language-javascript">res.json({
  success: true,
  message: "Data fetched successfully"
});
</code></pre>
<p>This is especially useful when building APIs.</p>
<h3>Express Routing Structure Visualization</h3>
<pre><code class="language-javascript">  
  Incoming Request
         ↓
  Express Server
         ↓
  Route Matching
         ↓
  Correct Route Handler
         ↓
  Response Returned
</code></pre>
<p>As applications grow larger, Express allows routes to be organized into separate files and modules, making backend code much easier to maintain.</p>
<hr />
<h2>Why Developers Prefer Express</h2>
<p>Express became the standard framework for Node.js because it removes a lot of complexity from backend development.</p>
<p>Instead of manually handling low-level server logic, developers can focus more on building application features.</p>
<p>It offers:</p>
<ul>
<li><p>clean routing</p>
</li>
<li><p>middleware support</p>
</li>
<li><p>easier request handling</p>
</li>
<li><p>faster API development</p>
</li>
<li><p>scalable project structure</p>
</li>
</ul>
<p>At the same time, Express stays lightweight and flexible, which is why it remains one of the most widely used Node.js frameworks today.</p>
<hr />
<h2>Conclusion</h2>
<p>Express.js simplified backend development for Node.js developers in a huge way.</p>
<p>Instead of writing repetitive server code manually, developers can define routes and handle requests using clean, readable syntax.</p>
<p>The most important thing to understand is this:</p>
<blockquote>
<p>A route listens for a request and sends back a response.</p>
</blockquote>
<p>That simple request-response cycle powers almost every web application and API on the internet.</p>
<p>And Express makes working with that cycle incredibly easy.</p>
]]></content:encoded></item><item><title><![CDATA[Why Node.js is Perfect for Building Fast Web Applications]]></title><description><![CDATA[Modern web applications are expected to feel instant. Whether it’s a chat app, streaming platform, dashboard, or API, users expect fast responses and smooth real-time experiences. Building application]]></description><link>https://blog.rohitchornele.online/why-node-js-is-perfect-for-building-fast-web-applications</link><guid isPermaLink="true">https://blog.rohitchornele.online/why-node-js-is-perfect-for-building-fast-web-applications</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Rohit Chornele]]></dc:creator><pubDate>Sun, 10 May 2026 14:28:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6688fdd59dfed4afe8f5b269/bcc0de8e-96ed-42cf-9367-40030f0033aa.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Modern web applications are expected to feel instant. Whether it’s a chat app, streaming platform, dashboard, or API, users expect fast responses and smooth real-time experiences. Building applications that can handle thousands of users efficiently is one of the biggest challenges in backend development.</p>
<p>That’s one of the main reasons Node.js became so popular.</p>
<p>Node.js introduced a different way of handling requests compared to many traditional backend technologies. Instead of creating heavy thread-based systems, Node.js focused on lightweight, event-driven, asynchronous processing.</p>
<p>The result was a runtime that could handle large numbers of concurrent connections with impressive efficiency.</p>
<p>In this article, we’ll understand what makes Node.js fast, how its architecture works, and why so many companies adopted it for modern web applications.</p>
<hr />
<h2>What Makes Node.js Fast</h2>
<p>One of the biggest reasons Node.js feels fast is that it avoids wasting time waiting.</p>
<p>Traditional backend servers often process requests in a blocking way. A request arrives, the server starts processing it, and if the server needs data from a database or file system, it waits until the operation finishes before moving to the next task.</p>
<p>That waiting time becomes expensive when thousands of users connect simultaneously.</p>
<p>Node.js approaches the problem differently.</p>
<p>Instead of blocking while waiting for slow operations, Node.js delegates those tasks and immediately continues handling other requests. This keeps the server productive almost all the time.</p>
<p>Another important reason behind Node.js performance is the:</p>
<p>V8</p>
<p>V8 compiles JavaScript into highly optimized machine code, making execution extremely fast. Combined with Node.js’s lightweight architecture, this creates a very efficient runtime for web applications.</p>
<hr />
<h2>Understanding Non-Blocking I/O</h2>
<p>To understand why Node.js performs so well, you first need to understand the idea of <strong>non-blocking I/O</strong>.</p>
<p>I/O stands for Input/Output operations, such as:</p>
<ul>
<li><p>database queries</p>
</li>
<li><p>file reading</p>
</li>
<li><p>API calls</p>
</li>
<li><p>network communication</p>
</li>
</ul>
<p>These operations usually take time.</p>
<p>In a blocking system, the server waits until the operation finishes.</p>
<p>In a non-blocking system like Node.js, the server starts the operation and immediately moves on to handle something else.</p>
<p>Imagine a restaurant chef.</p>
<p>A blocking chef takes one order and stands beside the stove waiting for the food to cook before accepting another order.</p>
<p>A smart chef works differently. They place the food on the stove, set a timer, and immediately start preparing the next order while the previous one cooks.</p>
<p>That’s exactly how Node.js handles asynchronous operations.</p>
<p>Instead of waiting, it keeps moving.</p>
<h3>Blocking vs Non-Blocking Request Handling</h3>
<p>Here’s the difference visually.</p>
<p><strong>Traditional Blocking Server :</strong></p>
<pre><code class="language-javascript">
Request 1 → Processing → Waiting → Response
Request 2 → Must Wait
Request 3 → Must Wait
</code></pre>
<p>If one request takes too long, other requests get delayed behind it.</p>
<p><strong>Node.js Non-Blocking Server :</strong></p>
<pre><code class="language-javascript">
Request 1 → Async Task Started
Request 2 → Processing
Request 3 → Processing
       ↓
Completed Tasks Return Later
</code></pre>
<p>Node.js keeps accepting and processing new requests while previous operations continue in the background.</p>
<p>This is one of the core reasons it scales so efficiently.</p>
<hr />
<h2>Event-Driven Architecture</h2>
<p>Another major strength of Node.js is its <strong>event-driven architecture</strong>.</p>
<p>Instead of continuously checking whether tasks are complete, Node.js listens for events.</p>
<p>For example:</p>
<ul>
<li><p>database query completed</p>
</li>
<li><p>file read finished</p>
</li>
<li><p>API response received</p>
</li>
<li><p>user connected</p>
</li>
</ul>
<p>When an event occurs, Node.js triggers the associated callback or handler.</p>
<p>This architecture works extremely well for applications involving lots of simultaneous activity because the server spends very little time sitting idle.</p>
<p>At the center of this system is the <strong>Event Loop</strong>, which continuously manages incoming requests, async operations, and completed tasks.</p>
<hr />
<h2>Understanding the Single-Threaded Model</h2>
<p>One thing that surprises many developers is that Node.js is single-threaded for JavaScript execution.</p>
<p>At first, this sounds like a weakness.</p>
<p>People naturally ask:</p>
<blockquote>
<p>“How can one thread handle thousands of users?”</p>
</blockquote>
<p>The answer is that Node.js focuses on <strong>concurrency</strong>, not direct parallelism.</p>
<p>Concurrency means handling multiple tasks efficiently without blocking. Parallelism means multiple tasks literally running at the same exact time on multiple CPU cores.</p>
<p>Node.js achieves excellent concurrency by using:</p>
<ul>
<li><p>non-blocking operations</p>
</li>
<li><p>async execution</p>
</li>
<li><p>event-driven processing</p>
</li>
</ul>
<p>The single thread mostly coordinates tasks instead of waiting for them.</p>
<p>That’s why Node.js can manage thousands of active connections without creating thousands of heavy threads.</p>
<h3>Event Loop Request Processing Visualization</h3>
<pre><code class="language-javascript">
  Incoming Requests
         ↓
  Event Loop Receives Tasks
         ↓
  Async Operations Delegated
         ↓
  Event Loop Continues Handling Requests
         ↓
  Completed Tasks Return
         ↓
  Responses Sent Back
</code></pre>
<p>This continuous flow is what allows Node.js servers to remain responsive even under heavy traffic.</p>
<hr />
<h2>Where Node.js Performs Best</h2>
<p>Node.js performs exceptionally well for applications that involve many simultaneous connections and lots of I/O operations.</p>
<p>It shines in scenarios like:</p>
<ul>
<li><p>REST APIs</p>
</li>
<li><p>real-time chat systems</p>
</li>
<li><p>streaming platforms</p>
</li>
<li><p>live dashboards</p>
</li>
<li><p>multiplayer games</p>
</li>
<li><p>collaboration tools</p>
</li>
<li><p>notification systems</p>
</li>
</ul>
<p>These applications spend most of their time waiting for external operations like databases or APIs rather than performing extremely heavy CPU calculations.</p>
<p>That makes them a perfect fit for Node.js’s asynchronous architecture.</p>
<hr />
<h2>Real-World Companies Using Node.js</h2>
<p>Many large companies adopted Node.js because of its scalability and real-time capabilities.</p>
<p>Popular companies that have used Node.js include:</p>
<ul>
<li><p>Netflix</p>
</li>
<li><p>LinkedIn</p>
</li>
<li><p>Uber</p>
</li>
<li><p>PayPal</p>
</li>
<li><p>Walmart</p>
</li>
</ul>
<p>These companies needed systems capable of handling huge numbers of concurrent users efficiently, and Node.js proved to be a strong fit for those requirements.</p>
<h3>Why Developers Love Node.js</h3>
<p>Performance is only part of the reason developers love Node.js.</p>
<p>Another huge advantage is that developers can use JavaScript on both:</p>
<ul>
<li><p>frontend</p>
</li>
<li><p>backend</p>
</li>
</ul>
<p>This simplifies development workflows and allows teams to share knowledge more easily.</p>
<p>The npm ecosystem also accelerated Node.js adoption by giving developers access to thousands of reusable packages and tools.</p>
<p>Combined with its fast development experience and scalable architecture, Node.js became one of the most important technologies in modern web development.</p>
<hr />
<h2>Conclusion</h2>
<p>Node.js became popular because it solved a very important problem:</p>
<blockquote>
<p>How do you handle large numbers of users efficiently without wasting resources?</p>
</blockquote>
<p>Its non-blocking I/O model, event-driven architecture, and lightweight concurrency system made it perfect for modern web applications that rely heavily on real-time communication and asynchronous operations.</p>
<p>The key idea behind Node.js performance is simple:</p>
<blockquote>
<p>Don’t wait. Keep processing other work.</p>
</blockquote>
<p>And that simple idea is exactly what makes Node.js so powerful for building fast, scalable web applications.</p>
]]></content:encoded></item><item><title><![CDATA[Setting Up Your First Node.js Application Step-by-Step]]></title><description><![CDATA[Starting with Node.js is much easier than most beginners expect. One of the reasons Node.js became so popular is that you can install it, write a JavaScript file, and run your first backend applicatio]]></description><link>https://blog.rohitchornele.online/setting-up-your-first-node-js-application-step-by-step</link><guid isPermaLink="true">https://blog.rohitchornele.online/setting-up-your-first-node-js-application-step-by-step</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[chaicode webdev cohort 2026]]></category><category><![CDATA[Node.js]]></category><dc:creator><![CDATA[Rohit Chornele]]></dc:creator><pubDate>Sun, 10 May 2026 14:12:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6688fdd59dfed4afe8f5b269/81f9d99d-2e40-4878-8d5c-baf66b303957.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Starting with Node.js is much easier than most beginners expect. One of the reasons Node.js became so popular is that you can install it, write a JavaScript file, and run your first backend application within minutes.</p>
<p>In this article, we’ll go step-by-step through the complete setup process. You’ll learn how to install Node.js, verify the installation, understand the Node REPL, create your first JavaScript file, and finally build a simple “Hello World” server.</p>
<p>The goal here is not to build a complex project, but to understand how Node.js actually runs JavaScript outside the browser.</p>
<hr />
<h2>Installing Node.js</h2>
<p>The first step is installing Node.js on your system.</p>
<p>When you install Node.js, two important things get installed:</p>
<ul>
<li><p>the Node.js runtime</p>
</li>
<li><p>npm (Node Package Manager)</p>
</li>
</ul>
<p>npm helps developers install libraries and tools later, but for now we’ll focus mainly on Node.js itself.</p>
<p>To install Node.js, go to: <a href="https://nodejs.org?utm_source=chatgpt.com">Node.js Official Website</a></p>
<p>You’ll usually see two versions:</p>
<ul>
<li><p>LTS (Long Term Support) → stable and recommended for most users</p>
</li>
<li><p>Current → latest features but less stable</p>
</li>
</ul>
<p>For beginners, the LTS version is the safest choice.</p>
<p>The installation process is mostly straightforward regardless of whether you use Windows, macOS, or Linux. Download the installer, follow the setup instructions, and Node.js will be added to your system.</p>
<hr />
<h2>Checking the Installation Using Terminal</h2>
<p>After installation, it’s important to confirm that Node.js is working correctly.</p>
<p>Open your terminal or command prompt and type:</p>
<pre><code class="language-plaintext">
node -v
</code></pre>
<p>If Node.js is installed properly, you’ll see something like:</p>
<pre><code class="language-plaintext">v22.5.1
</code></pre>
<p>This command simply shows the installed Node.js version.</p>
<p>You can also check npm using:</p>
<pre><code class="language-plaintext">
npm -v
</code></pre>
<p>This confirms that the Node Package Manager was installed successfully as well.</p>
<p>At this point, your system is ready to run JavaScript outside the browser.</p>
<hr />
<h2>Understanding the Node REPL</h2>
<p>Before creating files, it’s useful to understand something called the <strong>Node REPL</strong>.</p>
<p>REPL stands for:</p>
<ul>
<li><p>Read</p>
</li>
<li><p>Evaluate</p>
</li>
<li><p>Print</p>
</li>
<li><p>Loop</p>
</li>
</ul>
<p>It’s basically an interactive Node.js environment where you can write JavaScript directly in the terminal and instantly see the result.</p>
<p>To start the REPL, simply type:</p>
<pre><code class="language-javascript">node
</code></pre>
<p>You’ll enter an interactive mode that looks something like this:</p>
<pre><code class="language-javascript">
&gt;
</code></pre>
<p>Now you can write JavaScript directly.</p>
<p>Example :</p>
<pre><code class="language-javascript">
&gt; 2 + 3

&gt; 5  // output
</code></pre>
<p>You can also test variables and functions:</p>
<pre><code class="language-javascript">const name = "Rohit";

console.log(name);
</code></pre>
<p>The REPL is extremely useful for quick testing and experimentation because you don’t need to create separate files every time.</p>
<p>To exit the REPL press <code>ctrl + c</code> twice, or type:</p>
<pre><code class="language-plaintext">.exit
</code></pre>
<hr />
<h2>Creating Your First JavaScript File</h2>
<p>Now let’s create an actual Node.js program.</p>
<p>Create a new folder anywhere on your computer. Inside that folder, create a file called:</p>
<pre><code class="language-javascript">app.js
</code></pre>
<p>Open the file in your code editor and write:</p>
<pre><code class="language-javascript">console.log("Hello from Node.js");
</code></pre>
<p>This is your very first Node.js application.</p>
<p>Even though the code looks simple, something important is happening here:</p>
<blockquote>
<p>JavaScript is now running outside the browser.</p>
</blockquote>
<p>There’s no HTML page, no browser console, and no frontend UI involved.</p>
<p>Node.js is directly executing the JavaScript file on your system.</p>
<hr />
<h2>Running the Script Using the Node Command</h2>
<p>To execute the file, open the terminal inside your project folder and run:</p>
<pre><code class="language-javascript">node app.js
</code></pre>
<p>You should see:</p>
<pre><code class="language-javascript">Hello from Node.js
</code></pre>
<p>This is the basic Node.js execution flow:</p>
<pre><code class="language-javascript">  JavaScript File
         ↓
  Node.js Runtime
         ↓
  Execution
         ↓
  Terminal Output
</code></pre>
<p>The <code>node</code> command tells the Node.js runtime to execute the specified JavaScript file.</p>
<p>This is the foundation of every Node.js application.</p>
<hr />
<h2>Writing Your First Hello World Server</h2>
<p>Printing text is useful for understanding execution, but one of the biggest reasons developers use Node.js is to create servers.</p>
<p>Now let’s build a simple web server.</p>
<p>Replace the contents of <code>app.js</code> with this code:</p>
<pre><code class="language-javascript">
import http from 'http';

const server = http.createServer((req, res) =&gt; {
  res.end("Hello World from Node.js");
});

server.listen(3000, () =&gt; {
  console.log("Server running on port 3000");
});
</code></pre>
<p>At first, this code may look unfamiliar, but the idea is simple.</p>
<p>We are:</p>
<ol>
<li><p>importing Node’s built-in HTTP module</p>
</li>
<li><p>creating a server</p>
</li>
<li><p>sending a response</p>
</li>
<li><p>starting the server on port 3000</p>
</li>
</ol>
<p>Now run the file again:</p>
<pre><code class="language-javascript">node app.js
</code></pre>
<p>You’ll see:</p>
<pre><code class="language-javascript">Server running on port 3000
</code></pre>
<p>Open your browser and visit:</p>
<pre><code class="language-javascript">http://localhost:3000
</code></pre>
<p>You’ll see:</p>
<pre><code class="language-javascript">Hello World from Node.js
</code></pre>
<p>And just like that, you created your first backend server using Node.js.</p>
<h3>Understanding What Happened</h3>
<p>When the browser visited <code>localhost:3000</code>, it sent a request to your Node.js server.</p>
<p>The server received the request, processed it, and sent back a response containing:</p>
<pre><code class="language-javascript">
Hello World from Node.js
</code></pre>
<p>This is the same basic idea behind APIs and backend applications. Real-world applications become much more complex, but the core request-response cycle remains the same.</p>
<h3>Node.js Execution Flow</h3>
<p>Here’s a simplified flow of what happens internally:</p>
<pre><code class="language-javascript">  Browser Request
         ↓
  Node.js Server
         ↓
  Request Handler Executes
         ↓
  Response Sent Back
         ↓
  Browser Displays Result
</code></pre>
<p>Understanding this flow is extremely important because nearly every backend application works using this same principle.</p>
<hr />
<h2>Conclusion</h2>
<p>Setting up your first Node.js application is an important milestone because it introduces the core idea behind Node.js:</p>
<blockquote>
<p>JavaScript can run outside the browser.</p>
</blockquote>
<p>In this article, you learned how to:</p>
<ul>
<li><p>install Node.js</p>
</li>
<li><p>verify the installation</p>
</li>
<li><p>use the Node REPL</p>
</li>
<li><p>execute JavaScript files</p>
</li>
<li><p>create your first server</p>
</li>
</ul>
<p>More importantly, you saw how Node.js takes a JavaScript file, executes it through the runtime, and turns it into a working backend application.</p>
<p>And that’s where the real Node.js journey begins.</p>
]]></content:encoded></item><item><title><![CDATA[What is Node.js? JavaScript on the Server Explained]]></title><description><![CDATA[For a long time, JavaScript was seen as a browser-only language. Developers mainly used it to make websites interactive, things like form validation, dropdown menus, sliders, and dynamic UI updates. I]]></description><link>https://blog.rohitchornele.online/what-is-node-js-javascript-on-the-server-explained</link><guid isPermaLink="true">https://blog.rohitchornele.online/what-is-node-js-javascript-on-the-server-explained</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[Server-side JavaScript]]></category><dc:creator><![CDATA[Rohit Chornele]]></dc:creator><pubDate>Sun, 10 May 2026 13:42:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6688fdd59dfed4afe8f5b269/b0127fee-0918-4bad-87dd-a0308d7cb474.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>For a long time, JavaScript was seen as a browser-only language. Developers mainly used it to make websites interactive, things like form validation, dropdown menus, sliders, and dynamic UI updates. If you wanted to build the backend of an application, you usually had to learn another language such as PHP, Java, or Ruby.</p>
<p>But today, JavaScript is everywhere. Developers use it to build APIs, backend servers, chat applications, streaming platforms, and even desktop apps. A huge reason behind this transformation is Node.js.</p>
<p>Node.js completely changed how developers looked at JavaScript by allowing it to run outside the browser.</p>
<hr />
<h2>What Actually Node.js Is ?</h2>
<p>Node.js is a runtime environment that allows JavaScript to run on servers and computers outside the browser.</p>
<p>That definition sounds technical at first, but the idea is actually simple.</p>
<p>JavaScript itself is just a programming language. Like any language, it needs an environment where it can execute. Inside a browser like Chrome or Firefox, the browser provides that environment. It gives JavaScript access to things like buttons, forms, the DOM, and browser APIs.</p>
<p>Node.js provides a different environment. Instead of focusing on webpages and browser interactions, Node.js gives JavaScript access to server-side features like:</p>
<ul>
<li><p>file systems</p>
</li>
<li><p>databases</p>
</li>
<li><p>networking</p>
</li>
<li><p>operating system functionality</p>
</li>
</ul>
<p>This means JavaScript can now create web servers, handle APIs, read files, and manage backend logic — things that were previously impossible using browser JavaScript alone.</p>
<hr />
<h2>Why JavaScript Was Originally Browser-Only</h2>
<p>When JavaScript was created in 1995, its purpose was very different from what we use it for today. Websites at that time were mostly static. JavaScript was introduced to make webpages interactive without constantly reloading the page.</p>
<p>For example, clicking a button could instantly update content on the screen. Forms could validate user input before submission. Small interactive experiences became possible directly inside the browser.</p>
<p>Because of this, JavaScript became tightly connected to frontend development. Backend development remained in the hands of technologies like PHP and Java, which handled databases, authentication, and server-side logic.</p>
<p>For years, developers lived in a world where frontend and backend were completely separate ecosystems.</p>
<hr />
<h2>How Node.js Made JavaScript Run on Servers</h2>
<p>Everything changed in 2009 when Ryan Dahl introduced Node.js.</p>
<p>The idea behind Node.js was surprisingly powerful:</p>
<blockquote>
<p>What if JavaScript could run outside the browser?</p>
</blockquote>
<p>Instead of limiting JavaScript to frontend interactions, Node.js allowed developers to execute JavaScript directly on servers. This meant developers could finally use the same language for both frontend and backend development.</p>
<p>Before Node.js, a developer might write JavaScript for the frontend and PHP or Java for the backend. Switching between different languages and ecosystems added complexity to development.</p>
<p>Node.js simplified that workflow dramatically. Suddenly, full-stack JavaScript development became possible, and developers loved the idea of using one language across the entire application.</p>
<hr />
<h2>JavaScript Language vs Runtime Environment</h2>
<p>One thing that often confuses beginners is the difference between JavaScript itself and Node.js.</p>
<p>JavaScript is the language. Node.js is the runtime environment that executes that language outside the browser.</p>
<p>A simple analogy is to think of JavaScript as a recipe and the runtime as the kitchen where the recipe gets prepared. The recipe alone cannot produce food without a kitchen and tools.</p>
<p>Similarly, JavaScript code cannot execute by itself. It needs an environment.</p>
<p>Browsers provide one environment focused on webpages and UI interactions. Node.js provides another environment focused on backend and server functionality.</p>
<p>The language is the same, but the capabilities differ depending on where the code runs.</p>
<hr />
<h2>Browser JavaScript vs Node.js</h2>
<p>A good way to understand Node.js is by comparing browser JavaScript with server-side JavaScript.</p>
<p>Inside the browser, JavaScript usually reacts to user interactions.</p>
<pre><code class="language-javascript">
button.addEventListener("click", () =&gt; {
  alert("Button clicked!");
});
</code></pre>
<p>This code interacts with webpage elements and browser APIs.</p>
<p>Now compare that with Node.js:</p>
<pre><code class="language-javascript">
import http from 'node:http';

http.createServer((req, res) =&gt; {
  res.end("Hello from Node.js");
}).listen(3000);
</code></pre>
<p>This code creates an actual web server.</p>
<p>That’s the biggest shift Node.js introduced. JavaScript was no longer limited to webpages, it became capable of running entire backend applications.</p>
<h2>V8 Engine Overview</h2>
<p>Under the hood, Node.js uses the:</p>
<p><strong>V8</strong></p>
<p>V8 is the same JavaScript engine originally built for Google Chrome. Its job is to take JavaScript code and convert it into machine code that the computer can execute efficiently.</p>
<p>Node.js uses V8 outside the browser environment, which is what allows JavaScript to run on servers.</p>
<p>You don’t need to understand deep engine internals to work with Node.js. The important thing is simply this:</p>
<blockquote>
<p>V8 makes JavaScript execution fast.</p>
</blockquote>
<p>And Node.js uses that speed to build scalable applications.</p>
<hr />
<h2>Event-Driven Architecture in Node.js</h2>
<p>One of the biggest reasons developers adopted Node.js so quickly was its event-driven architecture.</p>
<p>Traditional backend systems often used a thread-based approach where each request occupied its own thread. As traffic increased, memory usage and server overhead increased as well.</p>
<p>Node.js approached the problem differently.</p>
<p>Instead of waiting for slow operations like database queries or file reads to finish, Node.js delegates those tasks and keeps processing other requests. This non-blocking model allows Node.js to handle many simultaneous connections efficiently without creating large numbers of threads.</p>
<p>That architecture made Node.js especially attractive for applications involving:</p>
<ul>
<li><p>real-time communication</p>
</li>
<li><p>streaming</p>
</li>
<li><p>APIs</p>
</li>
<li><p>live dashboards</p>
</li>
<li><p>chat systems</p>
</li>
</ul>
<p>The server remains responsive because it spends very little time sitting idle waiting for operations to complete.</p>
<hr />
<h2>Why Developers Adopted Node.js</h2>
<p>Node.js became popular not just because it was fast, but because it improved the overall developer experience.</p>
<p>Using JavaScript on both frontend and backend simplified development workflows. Teams could share knowledge, reuse logic, and work more consistently across projects.</p>
<p>At the same time, Node.js performed extremely well for I/O-heavy applications where servers spend most of their time waiting for external operations like databases or APIs.</p>
<p>Its package ecosystem through npm also played a massive role in its growth. Developers suddenly had access to thousands of reusable packages that accelerated development dramatically.</p>
<hr />
<h2>Real-World Use Cases of Node.js</h2>
<p>Today, Node.js powers a huge number of modern applications. It is commonly used for building APIs, real-time chat systems, streaming platforms, collaboration tools, multiplayer games, and microservices.</p>
<p>Its event-driven architecture makes it particularly effective for applications where many users stay connected simultaneously.</p>
<p>That’s why Node.js became one of the most important technologies in modern web development.</p>
<hr />
<h2>Conclusion</h2>
<p>Node.js changed the role of JavaScript completely.</p>
<p>What began as a browser scripting language evolved into a powerful backend technology capable of running scalable server applications.</p>
<p>The most important thing to remember is this:</p>
<blockquote>
<p>Node.js is not a programming language.<br />It is a runtime environment that allows JavaScript to run outside the browser.</p>
</blockquote>
<p>By combining JavaScript with the speed of the V8 engine and an event-driven architecture, Node.js made full-stack JavaScript development possible and transformed modern backend development forever.</p>
]]></content:encoded></item><item><title><![CDATA[Async Code in Node.js: Callbacks and Promises]]></title><description><![CDATA[One of the most important concepts in Node.js is asynchronous programming. If you’ve ever worked with file handling, APIs, or databases in Node.js, you’ve already used async code, even if you didn’t f]]></description><link>https://blog.rohitchornele.online/async-code-in-node-js-callbacks-and-promises</link><guid isPermaLink="true">https://blog.rohitchornele.online/async-code-in-node-js-callbacks-and-promises</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[asynchronous]]></category><category><![CDATA[Node.js]]></category><dc:creator><![CDATA[Rohit Chornele]]></dc:creator><pubDate>Sun, 10 May 2026 12:54:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6688fdd59dfed4afe8f5b269/3b9b18f3-ddbe-40ed-ad72-b53cfbd34148.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>One of the most important concepts in Node.js is asynchronous programming. If you’ve ever worked with file handling, APIs, or databases in Node.js, you’ve already used async code, even if you didn’t fully realize it.</p>
<p>At first, async programming can feel confusing because the code doesn’t always execute from top to bottom in a simple sequence. But once you understand <em>why</em> async code exists, callbacks and promises start making a lot more sense.</p>
<p>In this article, we’ll understand how asynchronous code works in Node.js, why callbacks were introduced, the problems they created, and how promises made async code cleaner and easier to manage.</p>
<hr />
<h2>Why Async Code Exists in Node.js</h2>
<p>Node.js was designed to handle multiple tasks efficiently without blocking the main thread. Most backend operations take time to complete, such as:</p>
<ul>
<li><p>reading files</p>
</li>
<li><p>querying databases</p>
</li>
<li><p>calling APIs</p>
</li>
<li><p>communicating over networks</p>
</li>
</ul>
<p>If Node.js waited for every operation to finish before moving to the next task, the server would become slow and unresponsive.</p>
<p>Imagine a restaurant chef preparing food. If the chef stopped everything and waited beside the oven for one pizza to bake before taking new orders, the restaurant would quickly become chaotic.</p>
<p>Instead, a smart chef puts the pizza in the oven and continues preparing other dishes while waiting.</p>
<p>That’s exactly how Node.js handles asynchronous operations.</p>
<h3>Starting with a File Reading Scenario</h3>
<p>Let’s take a simple example. Imagine you want to read a large file from the system.</p>
<p>Here’s the synchronous version:</p>
<pre><code class="language-javascript">
const fs = require("fs");

const data = fs.readFileSync("notes.txt", "utf8");

console.log(data);

console.log("Finished");
</code></pre>
<p>This code blocks execution. Node.js waits until the file is fully read before moving forward.</p>
<p>Now look at the asynchronous version :</p>
<pre><code class="language-javascript">
const fs = require("fs");

fs.readFile("notes.txt", "utf8", (err, data) =&gt; {
  console.log(data);
});

console.log("Finished");
</code></pre>
<p>This time, Node.js starts reading the file and immediately continues executing the next line. That’s why <code>"Finished"</code> gets printed before the file content appears.</p>
<p>Instead of waiting, Node.js keeps moving.</p>
<hr />
<h2>Callback-Based Async Execution</h2>
<p>The function passed inside <code>readFile()</code> is called a <strong>callback</strong>.</p>
<p>A callback is simply a function that runs later, after an operation completes.</p>
<p>In the previous example:</p>
<pre><code class="language-javascript">
(err, data) =&gt; {
  console.log(data);
}
</code></pre>
<p>this function does not execute immediately. Node.js stores it temporarily and runs it once the file reading operation finishes.</p>
<p>Here’s the flow step-by-step:</p>
<pre><code class="language-plaintext">
  Start File Read
        ↓
  Node.js Continues Execution
        ↓
  File Reading Completes
        ↓
  Callback Function Executes
</code></pre>
<p>Callbacks became the foundation of asynchronous programming in early Node.js applications because they allowed the event loop to stay free while slow operations happened in the background.</p>
<hr />
<h2>Problems with Nested Callbacks</h2>
<p>Callbacks solved the blocking problem, but they introduced another issue: deeply nested code.</p>
<p>Imagine a real-world situation where you need to:</p>
<ol>
<li><p>Read a file</p>
</li>
<li><p>Fetch data from an API</p>
</li>
<li><p>Save something into a database</p>
</li>
<li><p>Send a response</p>
</li>
</ol>
<p>Using callbacks, the code can quickly become messy.</p>
<pre><code class="language-javascript">
readFile("user.txt", (err, fileData) =&gt; {
  fetchUserData(fileData, (err, userData) =&gt; {
    saveToDatabase(userData, (err, result) =&gt; {
      sendResponse(result, (err) =&gt; {
        console.log("Done");
      });
    });
  });
});
</code></pre>
<p>Notice how the code keeps moving deeper and deeper toward the right side.</p>
<p>This problem became famously known as:</p>
<blockquote>
<p>“Callback Hell”</p>
</blockquote>
<p>or sometimes:</p>
<blockquote>
<p>“Pyramid of Doom”</p>
</blockquote>
<p>The biggest issue wasn’t just appearance. Nested callbacks made code:</p>
<ul>
<li><p>harder to read</p>
</li>
<li><p>difficult to debug</p>
</li>
<li><p>painful to maintain</p>
</li>
<li><p>harder to handle errors properly</p>
</li>
</ul>
<p>As applications grew larger, developers needed a cleaner way to manage async operations.</p>
<hr />
<h2>Promise-Based Async Handling</h2>
<p>To solve callback problems, JavaScript introduced <strong>Promises</strong>.</p>
<p>A Promise represents a value that may become available in the future.</p>
<p>Think of it like ordering food online.</p>
<p>When you place the order:</p>
<ul>
<li><p>you don’t receive the food immediately</p>
</li>
<li><p>you receive a promise that the food will arrive later</p>
</li>
</ul>
<p>The promise can eventually be:</p>
<ul>
<li><p>fulfilled → operation succeeded</p>
</li>
<li><p>rejected → operation failed</p>
</li>
</ul>
<pre><code class="language-javascript">
const fs = require("fs").promises;

fs.readFile("notes.txt", "utf8")
  .then((data) =&gt; {
    console.log(data);
  })
  .catch((err) =&gt; {
    console.log(err);
  });
</code></pre>
<p>Now the flow feels much cleaner.</p>
<p>Instead of nesting callbacks inside callbacks, promises allow operations to be chained in a more readable way.</p>
<h3>Promise Lifecycle</h3>
<p>A Promise usually goes through three states:</p>
<pre><code class="language-plaintext">  
  Pending
     ↓
  Fulfilled  → Success
     OR
  Rejected   → Error
</code></pre>
<p>When the async operation starts, the promise is in a <strong>pending</strong> state.</p>
<p>After completion:</p>
<ul>
<li><p>it becomes fulfilled if successful</p>
</li>
<li><p>rejected if something fails</p>
</li>
</ul>
<hr />
<h2>Comparing Callback vs Promise Readability</h2>
<p>Let’s compare both approaches side-by-side.</p>
<h3>Callback Style</h3>
<pre><code class="language-javascript">
getUser(id, (err, user) =&gt; {
  getPosts(user, (err, posts) =&gt; {
    getComments(posts, (err, comments) =&gt; {
      console.log(comments);
    });
  });
});
</code></pre>
<p>The code becomes deeply nested very quickly.</p>
<h3>Promise Style</h3>
<pre><code class="language-javascript">
getUser(id)
  .then((user) =&gt; getPosts(user))
  .then((posts) =&gt; getComments(posts))
  .then((comments) =&gt; console.log(comments))
  .catch((err) =&gt; console.log(err));
</code></pre>
<p>This version is much easier to read because the operations flow linearly from top to bottom.</p>
<p>That readability is one of the biggest reasons promises became so popular in modern JavaScript and Node.js development.</p>
<hr />
<h2>Benefits of Promises</h2>
<p>Promises improved asynchronous programming in several important ways.</p>
<p>They made code:</p>
<ul>
<li><p>cleaner and easier to read</p>
</li>
<li><p>easier to maintain</p>
</li>
<li><p>simpler to debug</p>
</li>
<li><p>better for error handling</p>
</li>
<li><p>easier to chain async operations together</p>
</li>
</ul>
<p>Most modern Node.js APIs now support promises directly because they work much better for large-scale applications.</p>
<p>Promises also became the foundation for <code>async/await</code>, which made asynchronous code look even more synchronous and readable.</p>
<hr />
<h2>Real-World Example</h2>
<p>Imagine an e-commerce application.</p>
<p>When a user opens their dashboard, the server may need to:</p>
<ul>
<li><p>fetch user details</p>
</li>
<li><p>load recent orders</p>
</li>
<li><p>retrieve notifications</p>
</li>
<li><p>fetch payment information</p>
</li>
</ul>
<p>All of these operations involve asynchronous tasks like database queries and API calls.</p>
<p>Without async programming, every user request would block the server while waiting for each operation to complete.</p>
<p>With callbacks and promises, Node.js can handle these tasks efficiently while still serving other users at the same time.</p>
<p>That’s one of the reasons Node.js performs so well for modern web applications.</p>
<hr />
<h2>Conclusion</h2>
<p>Async programming is at the heart of Node.js.</p>
<p>Callbacks were the first major solution for handling asynchronous operations without blocking the event loop. They worked well, but deeply nested callbacks quickly became difficult to manage.</p>
<p>Promises improved this experience by making async code cleaner, more readable, and easier to maintain.</p>
<p>The important thing to remember is this:</p>
<blockquote>
<p>Async code allows Node.js to stay productive while waiting for slow operations to complete.</p>
</blockquote>
<p>And that single idea is what makes Node.js capable of handling massive numbers of requests efficiently.</p>
]]></content:encoded></item><item><title><![CDATA[Blocking vs Non-Blocking Code in Node.js
]]></title><description><![CDATA[One of the biggest reasons Node.js is considered fast and scalable is its non-blocking architecture. If you’ve worked with backend development for some time, you’ve probably heard developers say thing]]></description><link>https://blog.rohitchornele.online/blocking-vs-non-blocking-code-in-node-js</link><guid isPermaLink="true">https://blog.rohitchornele.online/blocking-vs-non-blocking-code-in-node-js</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Blocking vs Non-Blocking Code in Node.js]]></category><category><![CDATA[Node.js]]></category><dc:creator><![CDATA[Rohit Chornele]]></dc:creator><pubDate>Sun, 10 May 2026 12:20:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6688fdd59dfed4afe8f5b269/66ca8721-38f8-42bc-9aee-e017ae2cab45.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>One of the biggest reasons Node.js is considered fast and scalable is its non-blocking architecture. If you’ve worked with backend development for some time, you’ve probably heard developers say things like:</p>
<blockquote>
<p>“Never block the event loop.”</p>
</blockquote>
<p>But what exactly does blocking mean? And why is non-blocking code such a big deal in Node.js?</p>
<p>To understand how Node.js handles thousands of requests efficiently, you first need to understand the difference between blocking and non-blocking execution.</p>
<h2>What Blocking Code Means</h2>
<p>Blocking code is code that stops the execution flow until a task finishes completely. While the operation is running, Node.js cannot move forward to execute the next piece of code.</p>
<p>Think of it like standing at a food counter waiting for your order. You place the order and then stand there doing absolutely nothing until the food arrives. Everything pauses during the waiting period.</p>
<p>That’s exactly how blocking code behaves.</p>
<p>In Node.js, operations like file reading, database queries, or network requests can take time. If the main thread waits for those operations to complete, the entire server becomes temporarily busy.</p>
<p>Here is a simple example :</p>
<pre><code class="language-javascript">
const fs = require("fs");

const data = fs.readFileSync("largeFile.txt", "utf8");

console.log(data);

console.log("Finished");
</code></pre>
<p>In this example, <code>readFileSync()</code> blocks execution. Node.js will not move to the next line until the file is fully read. During this time:</p>
<ul>
<li><p>the event loop is paused</p>
</li>
<li><p>incoming requests must wait</p>
</li>
<li><p>server responsiveness decreases</p>
</li>
</ul>
<h3>Blocking Execution Timeline</h3>
<pre><code class="language-plaintext">  
  Start File Read
        ↓
  Waiting...
  Waiting...
  Waiting...
        ↓
  File Read Complete
        ↓
  Next Code Executes
</code></pre>
<p>This may not look dangerous in small applications, but on a production server handling thousands of users, blocking operations quickly become a serious performance problem.</p>
<h2>What Non-Blocking Code Means</h2>
<p>Non-blocking code works differently. Instead of waiting for a task to finish, Node.js starts the operation, delegates it to the system, and immediately continues executing other code.</p>
<p>This allows the server to remain responsive even while slow operations are happening in the background.</p>
<p>Here’s the non-blocking version of the same file read:</p>
<pre><code class="language-javascript">
const fs = require("fs");

fs.readFile("largeFile.txt", "utf8", (err, data) =&gt; {
  console.log(data);
});

console.log("Finished");
</code></pre>
<p>This time, Node.js starts reading the file and immediately moves ahead. You’ll actually see <code>"Finished"</code> printed before the file content appears because the file operation happens asynchronously in the background.</p>
<p>Instead of waiting, Node.js keeps moving.</p>
<h3>Non-Blocking Execution Timeline</h3>
<pre><code class="language-plaintext">
  Start File Read
        ↓
  Continue Executing Other Code
        ↓
  Handle Other Requests
        ↓
  File Read Completes
        ↓
  Callback Executes
</code></pre>
<p>This behavior is one of the main reasons Node.js performs so efficiently under heavy traffic.</p>
<h2>Why Blocking Slows Servers</h2>
<p>Node.js uses a single main thread for JavaScript execution. That means if one operation blocks the thread, every other request also has to wait.</p>
<p>Imagine a restaurant with only one chef. If the chef spends 20 minutes preparing one complicated dish while ignoring everyone else, the entire restaurant slows down. New customers keep arriving, but nobody gets served until the chef finishes the current task.</p>
<p>Blocking code creates the same situation inside a server.</p>
<p>For example:</p>
<pre><code class="language-javascript">
const data = fs.readFileSync("hugeFile.txt");
</code></pre>
<p>While this file is being read:</p>
<ul>
<li><p>no other JavaScript can execute</p>
</li>
<li><p>incoming API requests are delayed</p>
</li>
<li><p>the event loop cannot continue processing tasks</p>
</li>
</ul>
<p>Even fast requests become slow because one blocking task occupies the thread.</p>
<p>This is why synchronous methods like:</p>
<ul>
<li><p><code>readFileSync()</code></p>
</li>
<li><p>heavy loops</p>
</li>
<li><p>CPU-intensive calculations</p>
</li>
</ul>
<p>should be used very carefully in Node.js applications.</p>
<h2>Async Operations in Node.js</h2>
<p>Node.js was built around asynchronous execution. Most backend tasks involve waiting for something external, such as:</p>
<ul>
<li><p>database responses</p>
</li>
<li><p>API calls</p>
</li>
<li><p>file systems</p>
</li>
<li><p>network communication</p>
</li>
</ul>
<p>Instead of waiting idly, Node.js delegates these operations and continues handling other users.</p>
<p>Under the hood, Node.js uses:</p>
<ul>
<li><p>the event loop</p>
</li>
<li><p>async I/O</p>
</li>
<li><p>background workers</p>
</li>
<li><p>operating system APIs</p>
</li>
</ul>
<p>to make this possible.</p>
<p>This architecture allows thousands of requests to remain “in progress” simultaneously without creating thousands of threads.</p>
<h3>Real-World Examples</h3>
<p>A very common example is file handling.</p>
<p>Using blocking code:</p>
<pre><code class="language-javascript">const fs = require("fs");

const data = fs.readFileSync("report.pdf");

console.log("File Loaded");
</code></pre>
<p>The server pauses until the file finishes loading.</p>
<p>Now compare that with the asynchronous version:</p>
<pre><code class="language-javascript">const fs = require("fs");

fs.readFile("report.pdf", (err, data) =&gt; {
  console.log("File Loaded");
});
</code></pre>
<p>Here, the file operation happens in the background while the server continues handling other users.</p>
<h2>Why Non-Blocking Makes Node.js Fast</h2>
<p>Most web applications are not CPU-heavy. They are mostly waiting for I/O operations like databases, APIs, and file systems.</p>
<p>Node.js takes advantage of this by using waiting time efficiently. Instead of freezing the server during I/O operations, it keeps serving other requests.</p>
<p>This makes Node.js especially powerful for applications like:</p>
<ul>
<li><p>REST APIs</p>
</li>
<li><p>chat systems</p>
</li>
<li><p>streaming platforms</p>
</li>
<li><p>real-time dashboards</p>
</li>
<li><p>multiplayer applications</p>
</li>
</ul>
<p>The architecture is lightweight, memory efficient, and highly scalable because the main thread rarely sits idle.</p>
<h2>Conclusion</h2>
<p>The difference between blocking and non-blocking code is one of the most important concepts in Node.js development.</p>
<p>Blocking code pauses execution and slows down the server. Non-blocking code allows Node.js to continue processing other tasks while slow operations happen in the background.</p>
<p>The core idea is simple:</p>
<blockquote>
<p>Blocking code waits.<br />Non-blocking code keeps moving.</p>
</blockquote>
<p>And that single difference is what makes Node.js capable of handling massive numbers of concurrent requests so efficiently.</p>
]]></content:encoded></item><item><title><![CDATA[How Node.js Handles Multiple Requests with a Single Thread]]></title><description><![CDATA[When developers first hear that Node.js is single-threaded, the first reaction is usually confusion.

“If there’s only one thread, how can Node.js handle thousands of users at the same time?”

Traditi]]></description><link>https://blog.rohitchornele.online/how-node-js-handles-multiple-requests-with-a-single-thread</link><guid isPermaLink="true">https://blog.rohitchornele.online/how-node-js-handles-multiple-requests-with-a-single-thread</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[single-threaded]]></category><dc:creator><![CDATA[Rohit Chornele]]></dc:creator><pubDate>Sun, 10 May 2026 11:57:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6688fdd59dfed4afe8f5b269/7854dafc-c068-4311-8411-0bd935b22abf.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When developers first hear that Node.js is <em>single-threaded</em>, the first reaction is usually confusion.</p>
<blockquote>
<p>“If there’s only one thread, how can Node.js handle thousands of users at the same time?”</p>
</blockquote>
<p>Traditional backend servers often create a separate thread for every incoming request. More users means more threads. More threads means more memory usage and more CPU overhead.</p>
<p>Node.js takes a completely different approach.</p>
<p>Instead of creating a thread for every request, Node.js follows a much smarter idea:</p>
<blockquote>
<p>Don’t wait. Delegate the work and keep moving.</p>
</blockquote>
<p>That simple principle is what makes Node.js extremely fast and scalable for modern web applications.</p>
<p>In this article, we’ll understand how Node.js handles multiple requests using a single thread, how the event loop works, and why this architecture performs so well.</p>
<h2>Single Threaded Nature of Node.js</h2>
<p>Before understanding Node.js, let’s simplify two important terms process and thread :</p>
<h3>Process vs Thread</h3>
<p>A <strong>process</strong> is a running application.</p>
<p>For example:</p>
<ul>
<li><p>Chrome browser = one process</p>
</li>
<li><p>VS Code = another process</p>
</li>
<li><p>Your Node.js app = another process</p>
</li>
</ul>
<p>A <strong>thread</strong> is a worker inside that process.</p>
<p>Think of a restaurant kitchen:</p>
<ul>
<li><p>Kitchen = process</p>
</li>
<li><p>Chefs = threads</p>
</li>
</ul>
<p>Many traditional servers use multiple chef threads to handle multiple requests simultaneously but Node.js works differently.</p>
<h3>Node.js Uses a Single Main Thread</h3>
<p>Node.js runs JavaScript on:</p>
<ul>
<li><p>one main thread</p>
</li>
<li><p>one call stack</p>
</li>
<li><p>one memory heap</p>
</li>
</ul>
<p>This means only one piece of JavaScript executes at a time.</p>
<p>At first, this sounds like a limitation.<br />But most backend applications spend the majority of their time:</p>
<ul>
<li><p>waiting for databases</p>
</li>
<li><p>waiting for APIs</p>
</li>
<li><p>waiting for file systems</p>
</li>
<li><p>waiting for network responses</p>
</li>
</ul>
<p>These are called <strong>I/O operations</strong>.</p>
<p>Instead of sitting idle and waiting for these operations to finish, Node.js delegates them and keeps handling other requests.</p>
<p>That’s the foundation of Node.js architecture.</p>
<h2>Event Loop Role in Concurrency</h2>
<p>The real power of Node.js comes from the Event Loop.</p>
<p>The event loop is a continuously running mechanism that checks:</p>
<ol>
<li><p>Is there a new task?</p>
</li>
<li><p>Is any async task completed?</p>
</li>
<li><p>Is there a callback waiting to execute?</p>
</li>
</ol>
<p>It keeps repeating this cycle extremely fast.</p>
<h3>The Chef Analogy</h3>
<p>Imagine a restaurant with only one chef.</p>
<p>A blocking system would work like this:</p>
<ol>
<li><p>Take Order #1</p>
</li>
<li><p>Cook it completely</p>
</li>
<li><p>Deliver it</p>
</li>
<li><p>Then take Order #2</p>
</li>
</ol>
<p>Every customer waits.</p>
<h3>How Node.js Works</h3>
<p>Node.js behaves like a smart chef.</p>
<ol>
<li><p>Takes Order #1</p>
</li>
<li><p>Puts steak on the grill</p>
</li>
<li><p>Sets a timer</p>
</li>
<li><p>Immediately starts Order #2</p>
</li>
<li><p>Then Order #3</p>
</li>
</ol>
<p>The chef doesn’t stand there watching the steak cook.</p>
<p>Instead:</p>
<ul>
<li><p>the grill handles cooking</p>
</li>
<li><p>timers notify when food is ready</p>
</li>
<li><p>the chef keeps serving customers</p>
</li>
</ul>
<p>That chef is the <strong>Event Loop</strong>.</p>
<p>This is how Node.js handles many requests concurrently without blocking the main thread.</p>
<h3>Concurrency vs Parallelism</h3>
<p>This is one of the most misunderstood concepts.</p>
<p><strong>Concurrency :</strong></p>
<p>Concurrency means:</p>
<blockquote>
<p>Multiple tasks making progress without blocking each other.</p>
</blockquote>
<p>Node.js is primarily concurrent.</p>
<p><strong>Parallelism :</strong></p>
<p>Parallelism means:</p>
<blockquote>
<p>Multiple tasks literally running at the same exact time on multiple CPU cores.</p>
</blockquote>
<p>Node.js does not execute JavaScript in parallel by default.</p>
<p>Instead, it efficiently switches between tasks using the event loop.</p>
<h2>Delegating Tasks to Background Workers</h2>
<p>Here’s something many beginners don’t realize:</p>
<blockquote>
<p>Node.js is single-threaded for JavaScript execution, but not everything runs on that single thread.</p>
</blockquote>
<p>Under the hood, Node.js uses:</p>
<p>libuv</p>
<p>libuv provides:</p>
<ul>
<li><p>the event loop</p>
</li>
<li><p>async I/O handling</p>
</li>
<li><p>thread pool support</p>
</li>
</ul>
<h3>What Gets Delegated?</h3>
<p>Certain operations are too slow to execute directly on the main thread.</p>
<p>Examples include:</p>
<ul>
<li><p>file system operations</p>
</li>
<li><p>DNS lookups</p>
</li>
<li><p>cryptography</p>
</li>
<li><p>compression</p>
</li>
</ul>
<p>These tasks are delegated to background worker threads.</p>
<p>Meanwhile, the main thread remains free to handle incoming requests.</p>
<p>For network operations like HTTP requests and database communication, Node.js often relies directly on the operating system’s asynchronous I/O system.</p>
<h3>Visual Flow</h3>
<pre><code class="language-javascript">
  Client Request
        ↓
  Main Thread Receives Request
        ↓
  Async Task Delegated
        ↓
  Background Worker / OS
        ↓
  Task Completes
        ↓
  Callback Queue
        ↓
  Event Loop Executes Callback
        ↓
  Response Sent
</code></pre>
<h1>Handling Multiple Client Requests</h1>
<p>Let’s say three users hit your API at the same time.</p>
<pre><code class="language-javascript">
app.get("/", async (req, res) =&gt; {
  const users = await fetchUsers();
  res.json(users);
});
</code></pre>
<p>Here’s what happens internally.Here’s what happens internally.</p>
<h3>Step 1: Request Arrives</h3>
<p>User A sends a request.</p>
<p>The main thread receives it.</p>
<h3>Step 2: Async Task Starts</h3>
<p>The database query is delegated immediately.</p>
<p>The main thread does <strong>not</strong> wait.</p>
<h3>Step 3: Event Loop Continues</h3>
<p>While User A’s database query runs in the background:</p>
<ul>
<li><p>User B request arrives</p>
</li>
<li><p>User C request arrives</p>
</li>
</ul>
<p>Node.js accepts both immediately.</p>
<h3>Step 4: Completed Tasks Return</h3>
<p>When database results are ready:</p>
<ul>
<li><p>callbacks enter the queue</p>
</li>
<li><p>event loop picks them up</p>
</li>
<li><p>responses are sent</p>
</li>
</ul>
<p>This creates the illusion that many things are happening simultaneously.</p>
<p>But internally:</p>
<ul>
<li><p>JavaScript still runs on one thread</p>
</li>
<li><p>Node.js simply avoids blocking it</p>
</li>
</ul>
<h3>Blocking vs Non-Blocking Example</h3>
<p><strong>Blocking Code :</strong></p>
<pre><code class="language-javascript">
const data = fs.readFileSync("largeFile.txt");
console.log(data);
</code></pre>
<p><strong>Problem</strong>:</p>
<ul>
<li><p>execution stops</p>
</li>
<li><p>event loop waits</p>
</li>
<li><p>other requests cannot be processed</p>
</li>
</ul>
<p><strong>Non-Blocking Code :</strong></p>
<pre><code class="language-javascript">
fs.readFile("largeFile.txt", (err, data) =&gt; {
  console.log(data);
});
</code></pre>
<p>Here:</p>
<ul>
<li><p>file reading happens in background</p>
</li>
<li><p>event loop continues running</p>
</li>
<li><p>other users can still be served</p>
</li>
</ul>
<p>This non-blocking behavior is the reason Node.js performs so efficiently.</p>
<h2>Why Node.js Scales Well</h2>
<p>Node.js performs exceptionally well for I/O-heavy applications because of its lightweight architecture.</p>
<h3>Low Memory Usage</h3>
<p>Traditional servers create one thread per request.</p>
<p>More threads mean:</p>
<ul>
<li><p>more RAM usage</p>
</li>
<li><p>more CPU scheduling</p>
</li>
<li><p>more overhead</p>
</li>
</ul>
<p>Node.js avoids this by using a single event loop.</p>
<p>Thousands of connections can remain open with relatively low memory usage.</p>
<h3>Efficient Handling of I/O Operations</h3>
<p>Most backend applications spend more time waiting than computing.</p>
<p>For example:</p>
<ul>
<li><p>waiting for databases</p>
</li>
<li><p>waiting for APIs</p>
</li>
<li><p>waiting for file reads</p>
</li>
</ul>
<p>Node.js uses this waiting time efficiently by continuing to serve other users.</p>
<h3>Minimal Context Switching</h3>
<p>In multi-threaded systems, the operating system constantly switches between threads.</p>
<p>This process is called <strong>context switching</strong>, and it adds overhead.</p>
<p>Since Node.js mainly uses one thread for JavaScript execution, it avoids most of that overhead.</p>
<h3>Best for Real-Time Applications</h3>
<p>Node.js works especially well for:</p>
<ul>
<li><p>APIs</p>
</li>
<li><p>chat applications</p>
</li>
<li><p>streaming platforms</p>
</li>
<li><p>real-time dashboards</p>
</li>
<li><p>multiplayer games</p>
</li>
</ul>
<p>Anywhere many users stay connected simultaneously, Node.js performs extremely well.</p>
<h2>Conclusion</h2>
<p>The biggest misconception about Node.js is:</p>
<blockquote>
<p>“Single-threaded means it can only handle one request at a time.”</p>
</blockquote>
<p>That’s not true.</p>
<p>Node.js handles thousands of concurrent requests efficiently because it never wastes time waiting for slow operations to complete.</p>
<p>Instead:</p>
<ul>
<li><p>async tasks run in the background</p>
</li>
<li><p>the event loop keeps moving</p>
</li>
<li><p>completed operations return through callbacks</p>
</li>
</ul>
<p>The result is a lightweight, fast, and highly scalable backend architecture.</p>
<p>Once you understand the event loop and non-blocking I/O, the magic behind Node.js starts making perfect sense.</p>
]]></content:encoded></item><item><title><![CDATA[React's Virtual DOM : Behind the Scenes]]></title><description><![CDATA[If you've worked with React even for a little while, you've probably heard about the Virtual DOM. People often say it's one of the main reasons React feels fast and efficient. But what does it actuall]]></description><link>https://blog.rohitchornele.online/react-virtual-dom</link><guid isPermaLink="true">https://blog.rohitchornele.online/react-virtual-dom</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[React Native]]></category><category><![CDATA[React]]></category><category><![CDATA[virtual dom]]></category><dc:creator><![CDATA[Rohit Chornele]]></dc:creator><pubDate>Fri, 08 May 2026 18:42:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6688fdd59dfed4afe8f5b269/22856ed6-a979-4066-a1e5-9ad99767f003.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you've worked with React even for a little while, you've probably heard about the Virtual DOM. People often say it's one of the main reasons React feels fast and efficient. But what does it actually mean? Why was it introduced? And what really happens behind the scenes when a component updates?</p>
<p>In this article, we'll break everything down step by step, starting from the problem the Virtual DOM was designed to solve, all the way to how React updates only the necessary parts of the UI to keep your app smooth and performant.</p>
<h2><strong>The Problem: Why Direct DOM Manipulation Is Slow</strong></h2>
<p>To understand why the Virtual DOM exists, you first need to understand the problem it solves.</p>
<p>The browser's Real DOM, or Document Object Model, is a tree-like structure of your HTML elements. Whenever something changes on the page, like updating text, adding an element, or changing a class name, the browser has to perform several tasks:</p>
<ul>
<li><p>Recalculate styles</p>
</li>
<li><p>Reflow the layout to reposition elements</p>
</li>
<li><p>Repaint the updated content on the screen</p>
</li>
</ul>
<p>These operations are expensive, especially when updates happen frequently.</p>
<p>For small websites, this is usually fine. But modern web apps constantly update their UI. Users type into inputs, lists refresh, counters change, and components re-render. If every change directly updates the Real DOM, the browser ends up doing a lot of unnecessary work.</p>
<p>This was a common problem in early jQuery applications. Developers manually updated DOM elements, but as apps became more complex, keeping the UI in sync became difficult and error-prone.</p>
<p>React introduced the Virtual DOM to make this update process faster and more efficient.</p>
<h2>Real DOM vs Virtual DOM</h2>
<p>Before understanding how React works internally, it's important to know the difference between the Real DOM and the Virtual DOM.</p>
<p>The Real DOM is the actual tree of HTML elements that the browser renders on the screen. It is heavy and expensive to update because every change can trigger layout calculations and re-rendering.</p>
<p>The Virtual DOM is a lightweight JavaScript object that mirrors the Real DOM. It is just data, so creating and updating it is much faster.</p>
<p>Think of the Real DOM as the actual house, and the Virtual DOM as its blueprint. Changing a blueprint is quick and easy, while modifying the real house takes more effort.</p>
<p>React first updates the Virtual DOM, finds the minimum changes required, and then updates only those parts in the Real DOM.</p>
<p>Here's a simple mental model of what a Virtual DOM node looks like:</p>
<pre><code class="language-javascript">
// JSX you write:

&lt;div className="card"&gt;
  &lt;h2&gt;Hello, World&lt;/h2&gt;
  &lt;p&gt;Welcome to React&lt;/p&gt;
&lt;/div&gt;


// Gets turned into a Virtual DOM object like:
{
  type: 'div',
  props: { className: 'card' },
  children: [
    {
      type: 'h2',
      props: {},
      children: ['Hello, World']
    },
    {
      type: 'p',
      props: {},
      children: ['Welcome to React']
    }
  ]
}
</code></pre>
<p>This object lives entirely in memory. React can create, compare, and throw away these objects at will, all without touching the browser.</p>
<h2>The Initial Render Process</h2>
<p>When your React application loads for the first time, this is what happens step by step:</p>
<p><strong>Step 1 - React reads your components</strong><br />You create components as functions or classes that return JSX. React calls these components and collects their JSX output.</p>
<p><strong>Step 2 - JSX gets converted into JavaScript</strong><br />JSX is not understood directly by the browser. Babel compiles it into <code>React.createElement()</code> calls, which create Virtual DOM objects.</p>
<p><strong>Step 3 - React creates the Virtual DOM tree</strong><br />Starting from the root component, usually <code>&lt;App /&gt;</code>, React recursively processes all components and builds one complete Virtual DOM tree.</p>
<p><strong>Step 4 - React updates the Real DOM</strong><br />React converts the Virtual DOM into actual DOM elements and inserts them into the browser. This is the only time React builds the entire UI from scratch. Future updates only change the necessary parts instead of rebuilding everythin g.</p>
<pre><code class="language-plaintext">
 Component Functions
        ↓
     JSX → React.createElement()
        ↓
  Virtual DOM Tree (in memory)
        ↓
  Real DOM (browser renders it)
</code></pre>
<h2>How State or Props Changes Trigger a Re-render</h2>
<p>Once the app is running, a state or prop change can trigger a re-render. For example, a user clicks a button that calls <code>setState</code>, or a parent component passes new props.</p>
<p>React marks that component as needing an update. During the next render cycle, React calls the component again with the updated state or props. The component returns new JSX, and React creates a new Virtual DOM tree from it.</p>
<p>An important thing to understand is that React does not update the Real DOM immediately. It first creates the updated Virtual DOM completely in memory, then compares it with the previous version.</p>
<p>This is what makes React efficient. Most of the work happens on lightweight JavaScript objects, while the Real DOM is updated only where changes are actually needed.</p>
<h2>Creating a New Virtual DOM Tree</h2>
<p>Every time a component re-renders, React creates a new Virtual DOM subtree for that component and its children. This new tree represents how the UI should look based on the latest state and props.</p>
<p>Consider a simple counter:</p>
<pre><code class="language-javascript">
function Counter() {
  const [count, setCount] = useState(0);

  return (
    &lt;div&gt;
      &lt;p&gt;Count: {count}&lt;/p&gt;
      &lt;button onClick={() =&gt; setCount(count + 1)}&gt;Increment&lt;/button&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<p>When <code>count</code> is <code>0</code>, the Virtual DOM tree looks like:</p>
<pre><code class="language-javascript">
{
  type: 'div',
  children: [
    { type: 'p', children: ['Count: 0'] },
    { type: 'button', children: ['Increment'] }
  ]
}
</code></pre>
<p>After the button is clicked, <code>count</code> becomes <code>1</code>, and React creates a <strong>new</strong> Virtual DOM tree:</p>
<pre><code class="language-javascript">{
  type: 'div',
  children: [
    { type: 'p', children: ['Count: 1'] },  // ← changed
    { type: 'button', children: ['Increment'] }  // ← same
  ]
}
</code></pre>
<p>At this point, React has two Virtual DOM trees, the old tree from the previous render and the new tree from the current render. React then compares both trees to find what has changed.</p>
<h2>Diffing and Reconciliation</h2>
<p>Reconciliation is the process React uses to compare the old Virtual DOM tree with the new one to detect changes. This comparison process is called diffing.</p>
<p>Comparing two large trees can be very expensive, but React uses smart rules to make it fast and efficient.</p>
<p><strong>Rule 1 - Different element types create different trees</strong><br />If a <code>&lt;div&gt;</code> changes to a <code>&lt;section&gt;</code>, React removes the old subtree and creates a new one instead of comparing them deeply.</p>
<p><strong>Rule 2 - Keys help React track list items</strong><br />When rendering lists, React uses the <code>key</code> prop to identify items between renders. Without keys, React assumes items in the same position are the same, which can cause incorrect updates.</p>
<p>This is why React warns you about missing keys in lists. Keys help the diffing algorithm work correctly and efficiently.</p>
<h2>How React Finds the Minimal Required Changes</h2>
<p>During diffing, React compares the old and new Virtual DOM trees node by node.</p>
<p>At each step, React checks:</p>
<ul>
<li><p>Is the element type the same?<br />If a <code>&lt;p&gt;</code> is still a <code>&lt;p&gt;</code>, React keeps the existing DOM node. If the type changes, React removes the old node and creates a new one.</p>
</li>
<li><p>Did the props change?<br />If properties like <code>className</code>, <code>style</code>, or <code>onClick</code> changed, React updates only those specific attributes.</p>
</li>
<li><p>Did the children change?<br />React recursively compares child elements and applies the same process.</p>
</li>
<li><p>For lists, do the keys match?<br />React uses <code>key</code> props to identify which items were added, removed, or moved.</p>
</li>
</ul>
<p>After diffing, React creates a minimal list of updates needed for the Real DOM. For example, in a counter app, React may only update the text from <code>"Count: 0"</code> to <code>"Count: 1"</code> while leaving the button unchanged.</p>
<h2>Updating Only the Changed Nodes in the Real DOM</h2>
<p>Once diffing is finished, React enters the commit phase. This is the stage where React finally updates the browser's Real DOM.</p>
<p>React only applies the changes identified during diffing, such as:</p>
<ul>
<li><p>Updating text content</p>
</li>
<li><p>Changing an attribute</p>
</li>
<li><p>Adding a new DOM element</p>
</li>
<li><p>Removing an old element</p>
</li>
</ul>
<p>Since React already calculated everything using the Virtual DOM, the actual DOM updates are minimal and efficient. This reduces expensive browser operations like reflow and repaint.</p>
<p>In a counter example, React only updates the text inside the <code>&lt;p&gt;</code> tag from <code>"Count: 0"</code> to <code>"Count: 1"</code>. The <code>&lt;button&gt;</code> and the rest of the page remain unchanged.</p>
<h2>Why This Approach Improves Performance</h2>
<p>Now let's understand why this architecture works so well.</p>
<p><strong>Batching updates</strong><br />React can combine multiple state updates into a single render cycle. Instead of updating the DOM multiple times, React creates one optimized update.</p>
<p><strong>Avoiding unnecessary work</strong><br />React compares the old and new Virtual DOM trees first. If nothing changed, it skips updating the Real DOM completely.</p>
<p><strong>Reducing expensive browser operations</strong><br />Traditional JavaScript often mixes DOM reads and writes, which can force repeated layout recalculations. React avoids this by applying DOM updates together during the commit phase.</p>
<p><strong>Predictable UI updates</strong><br />Since React manages DOM updates itself, the UI stays in sync with the application state without manual DOM handling.</p>
<p>The Virtual DOM is not magic, it also has some overhead because React needs to create and compare JavaScript objects. But in most real-world applications, reducing expensive Real DOM operations gives a much bigger performance benefit.</p>
<h2>The Full React Update Lifecycle: Render → Diff → Commit</h2>
<p>Let's tie everything together into one clear flow.</p>
<pre><code class="language-js">┌──────────────────────────────────┐
│             TRIGGER                                  │
│ State / Props / forceUpdate                          │
└────────────────┬─────────────────┘
                 │
                 ▼
┌──────────────────────────────────┐
│          RENDER PHASE                                │
│ React re-renders components                          │
│ Creates new Virtual DOM tree                         │
│ No Real DOM updates yet                              │
└────────────────┬─────────────────┘
                 │
                 ▼
┌──────────────────────────────────┐
│           DIFF PHASE                                 │
│ Compare old vs new VDOM                              │
│ Detect changed nodes                                 │
│ Create minimal patch list                            │
└────────────────┬─────────────────┘
                 │
                 ▼
┌──────────────────────────────────┐
│         COMMIT PHASE                                 │
│ Update changed Real DOM nodes                        │
│ Browser repaints necessary UI                        │
│ useEffect runs after commit                          │
└──────────────────────────────────┘
</code></pre>
<p>The React update process is divided into three main phases:</p>
<p><strong>Render phase</strong> - React calculates what the UI should look like based on the latest state and props. This work happens only in memory using the Virtual DOM.</p>
<p><strong>Diff phase</strong> - React compares the new Virtual DOM tree with the previous one to find what changed. This is where reconciliation happens.</p>
<p><strong>Commit phase</strong> - React updates the Real DOM with only the required changes. Effects like <code>useEffect</code> also run after this phase.</p>
<h2>Conclusion</h2>
<p>The Virtual DOM is one of React's core concepts, but its main purpose is simple, keeping the UI updated efficiently without developers manually handling DOM changes.</p>
<p>Here’s the mental model to remember:</p>
<ul>
<li><p>The Real DOM is expensive to update</p>
</li>
<li><p>The Virtual DOM is a lightweight in-memory copy</p>
</li>
<li><p>React compares the old and new Virtual DOM trees through diffing</p>
</li>
<li><p>Only the required changes are applied to the Real DOM</p>
</li>
</ul>
<p>This render → diff → commit cycle keeps running as users interact with your app, state changes, or new data arrives. React handles the complex DOM updates internally, so developers only need to describe how the UI should look for a given state.</p>
<p>Understanding this flow also helps you use optimization tools like <code>React.memo</code>, <code>useMemo</code>, <code>useCallback</code>, and <code>key</code> props more effectively, because all of them help React reduce unnecessary work during diffing.</p>
]]></content:encoded></item><item><title><![CDATA[The Node.js Event Loop]]></title><description><![CDATA[We all know that the Node.js runs on single threaded architecture, still it handles thousands of concurrent operations, and this makes us think.... How is that even possible ?
The answer can be found ]]></description><link>https://blog.rohitchornele.online/the-node-js-event-loop</link><guid isPermaLink="true">https://blog.rohitchornele.online/the-node-js-event-loop</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[Event Loop]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Rohit Chornele]]></dc:creator><pubDate>Mon, 27 Apr 2026 07:50:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6688fdd59dfed4afe8f5b269/6a21c1ee-6666-464c-8292-ebc15b4a7d29.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We all know that the Node.js runs on single threaded architecture, still it handles thousands of concurrent operations, and this makes us think.... How is that even possible ?</p>
<p>The answer can be found in one of the most important concept of Node.js : The Event Loop.</p>
<p>In this article we are going to understand everything about Event loop and it's internals in detail.</p>
<h2>The Problem :</h2>
<p>Javascript was originally designed for browsers, an environment where only one UI thread runs at a time.</p>
<p>Node.js inherited the same model, this means Node.js can only execute one piece of code at any given point of time. There is no parallel execution of JS code by default.</p>
<p>This is not good for any web server, imagine 1000 users hit your server at the same moment, and each request requires a 2 seconds to complete the databse query. A traditional multi-threaded server would spin a new thread for each request, means 1000 threads running in parallel. It works, but it is expensive, each thread will also consume memory (roughly 1-2 mb), and coordinating between threads will increase complexity.</p>
<p>Node.js uses a very different approach, instead of handling parallel execution through threads, it handles it through a mechanism called the <strong>Event Loop</strong>, by never blocking and delegating works that involves waiting.</p>
<h2>What Is Event Loop ?</h2>
<p>In general, we can assume the event loop as a smart and tireless task manager, which runs a continuous check of :</p>
<ul>
<li><p>Check if the call stack is empty or is JavaScript currently executing anything?</p>
</li>
<li><p>If the stack is empty, check the queues are there any callbacks waiting to be run?</p>
</li>
<li><p>If there are, pick the highest-priority one and push it onto the call stack for execution.</p>
</li>
<li><p>Repeat this forever until the program ends.</p>
</li>
</ul>
<p>We can understand the flow of event loop with below diagram :</p>
<img src="https://cdn.hashnode.com/uploads/covers/6688fdd59dfed4afe8f5b269/785ec37d-c6c4-402a-aac8-6e050a8251f3.png" alt="" style="display:block;margin:0 auto" />

<p>This event loop, never sleeps, never blocks, it never waits, and never does any computation itself. It is purely an orchestrator, constantly checking, picking, and dispatching.</p>
<h2>Why Node.js Needs An Event Loop</h2>
<p>Without the event loop :</p>
<ul>
<li><p>Every request will blovk the thread</p>
</li>
<li><p>No parallel handling of user</p>
</li>
<li><p>Poor perfomrance and scalabiliy</p>
</li>
</ul>
<p>With the event loop:</p>
<ul>
<li><p>Non-blocking execution</p>
</li>
<li><p>Faster response handling</p>
</li>
<li><p>Efficient resource usage</p>
</li>
</ul>
<h2>Two Pillers Of The Event Loop :</h2>
<p>To understand the Event Loop deeply, we need to understand the two data structures event loop bridges:</p>
<ol>
<li><p>Call Stack</p>
</li>
<li><p>Task Queue</p>
</li>
</ol>
<h3>Call Stack :</h3>
<p>The call stack is the area where the Javascript functions actually executes. It works like a stack of items, whichever comes last, goes out first ( LIFO : Last in First out ).</p>
<p>When a function is called, a new frame is pushed onto the top of the call stack, when it returns, the frame is popped off. This stack can only process one frame at a time, and it processes them synchronously from top to bottom. If a function takes 3 seconds to complete, the entire stack is frozen for those 3 seconds.</p>
<h3>Task Queue :</h3>
<p>The task queue, aslo called the callback queue is a waiting room for async callbacks, when an async operation completes, a timer fires, a file finishes reading, a network response arrives. It's callback is placed here. The queue works on the approach of FIFO : First in First out.</p>
<p>Crucially, callbacks in this queue do nothing until the event loop picks them up and the call stack is empty.</p>
<p>These two structures form the backbone of everything async in Node.js. The call stack is where work happens right now. The task queue is where work waits to happen later. The event loop is what connects them.</p>
<h2>How Async Operations Really Work :</h2>
<p>When you call async function like setTimeout, fs.readFile or fetch, Node.js does not pause and wait for it to finish, It hands off the work to libuv.</p>
<p>libuv is C library, which works with Node.js that interface directly with the Operating System's async APIs.</p>
<p>libuv manages a thread pool for I/O-heavy work and uses OS-level event notification systems (like epoll on Linux or kqueue on macOS) to know when operations complete.</p>
<p>This means the Node.js JavaScript thread is free to keep running while libuv handles the heavy lifting in the background. When the OS reports that an operation is done, libuv puts the callback into the appropriate queue. The event loop picks it up the next time the call stack is clear.</p>
<pre><code class="language-javascript">console.log("Start");        
// 1. Pushed onto stack, runs immediately


setTimeout(() =&gt; {
  console.log("Timer done"); 
}, 2000);                     
// 3. Runs AFTER the stack is empty (not "after 2 seconds" exactly)


console.log("End");          
// 2. Pushed onto stack, runs immediately
</code></pre>
<pre><code class="language-plaintext">1  Start
2  End
3  Timer done
</code></pre>
<p>What happens step by step: <code>console.log("Start")</code> runs synchronously. <code>setTimeout</code> is encountered : Node immediately registers the timer with libuv and moves on without waiting. <code>console.log("End")</code> runs synchronously.</p>
<p>Now the stack is empty. After 2 seconds, libuv places the timer callback in the queue. The event loop detects the empty stack, picks the callback, and runs it. Only then does "Timer done" print.</p>
<h2>Timers vs I/O Callbacks</h2>
<p>Node.js handles different types of async operations in separate queues, and understanding the difference between the two main categories is important.</p>
<h3>Timers :</h3>
<p><code>setTimeout()</code> and <code>setInterval()</code> are time-based. Their callbacks enter the timer queue after a specified minimum delay has elapsed. "Minimum" is important here, if the event loop is busy processing something else when the timer fires, the callback waits until the current work is done. You can't guarantee exact timing with these.</p>
<h3>I/O Callbacks</h3>
<p>File reads, database queries, HTTP requests etc. these are completion-based. Their callbacks fire when the OS reports the operation is finished, regardless of time. A fast SSD might complete a file read in microseconds; a slow network request might take 5 seconds. The callback fires when it's ready, not on a clock.</p>
<p>The key conceptual difference: timers depend on time passing, I/O depends on something external finishing. Both go through libuv, and both end up in queues that the event loop manages, but they live in different queues with different priorities.</p>
<h2>Queue Priority (The Order That Matters)</h2>
<p>Not all queues are treated equally by the event loop. Every single "tick" of the loop, it processes queues in a strict, defined order.</p>
<table>
<thead>
<tr>
<th><strong>Queue</strong></th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Microtask</strong></td>
<td><code>Promise.then()</code> and <code>process.nextTick()</code>. These run first, and the entire microtask queue is drained completely before moving on to anything else. This means a long chain of resolved promises can delay timers and I/O callbacks.</td>
</tr>
<tr>
<td><strong>Timers</strong></td>
<td><code>setTimeout()</code> and <code>setInterval()</code> callbacks whose delay has elapsed. Processed after all microtasks are done for this tick.</td>
</tr>
<tr>
<td><strong>I/O</strong></td>
<td>Callbacks from file system operations, network requests, database queries. Run after timers in the same loop cycle.</td>
</tr>
<tr>
<td><strong>Check</strong></td>
<td><code>setImmediate()</code> callbacks. These are designed to run right after I/O callbacks in the same loop iteration — useful when you want something to run "after I/O but before the next timer check."</td>
</tr>
<tr>
<td><strong>Close</strong></td>
<td>Cleanup callbacks, for example, a <code>socket.on('close', ...)</code> handler. These run last in each cycle.</td>
</tr>
</tbody></table>
<p>Microtasks always cut the queue. A resolved <code>Promise.then()</code> will always run before any <code>setTimeout(fn, 0)</code>, even if both are ready at the same time.</p>
<h2>Role of Event Loop in Scalability</h2>
<p>All of this design has a powerful payoff. Because Node.js never creates a new thread per request, the memory cost of concurrency is dramatically lower than traditional servers.</p>
<ul>
<li><p>10,000 concurrent connections in Node.js = 10,000 callbacks in a queue, not 10,000 threads eating RAM.</p>
</li>
<li><p>No thread synchronization required — one thread means no race conditions in your application code.</p>
</li>
<li><p>I/O operations never block the main thread — while one request waits for a DB query, the event loop is already handling the next request.</p>
</li>
<li><p>Startup is fast, memory footprint stays lean even under heavy traffic.</p>
</li>
</ul>
<p>This is why Node.js is the go-to choice for real-time applications (chat, live notifications, multiplayer games), REST APIs that are I/O-bound rather than CPU-bound, and streaming services where thousands of open connections must be maintained simultaneously.</p>
<h2>Real World Analogy</h2>
<p>Here's a mental model that maps the whole system to something familiar.</p>
<table>
<thead>
<tr>
<th>Queue</th>
<th>Role Comparision</th>
<th>Working</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Call Stack</strong></td>
<td>The Chef</td>
<td>Can only cook one dish at a time. Fully focused on the current task — nothing else happens while the chef is cooking.</td>
</tr>
<tr>
<td><strong>Task Queue</strong></td>
<td>The Order Tickets</td>
<td>Completed orders pile up here, waiting to be picked up. The kitchen doesn't stop taking orders just because there's a queue.</td>
</tr>
<tr>
<td><strong>Event loop</strong></td>
<td>The Manager</td>
<td>Watches the chef and the ticket rail constantly. The moment the chef is free, the manager hands over the next ticket.</td>
</tr>
</tbody></table>
<p>The manager (event loop) never cooks and never takes food to tables. They just keep the kitchen running — the instant the chef (call stack) finishes one dish, the manager hands them the next ticket (callback). And when the kitchen is completely empty and quiet, the manager stands by the door waiting for the next customer order to arrive — that's the event loop blocking on the OS when all queues are empty, waiting for new I/O events.</p>
]]></content:encoded></item><item><title><![CDATA[The Linux File System]]></title><description><![CDATA[In this article, we are going to learn about the Linux File System, this article is no going to be another list of linux commands, but this will help you to know some rarely used and less known but im]]></description><link>https://blog.rohitchornele.online/the-linux-file-system</link><guid isPermaLink="true">https://blog.rohitchornele.online/the-linux-file-system</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[Linux]]></category><category><![CDATA[file system]]></category><dc:creator><![CDATA[Rohit Chornele]]></dc:creator><pubDate>Wed, 22 Apr 2026 15:03:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6688fdd59dfed4afe8f5b269/bea5976c-e45f-43bf-b4cf-229e0bcf28f2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this article, we are going to learn about the Linux File System, this article is no going to be another list of linux commands, but this will help you to know some rarely used and less known but important features of Linux file system.</p>
<p>Before diving into the advance features, It is a good idea to know about the basic commands of Linux file system.</p>
<h2>Filesystem Commands ( Frequently used )</h2>
<p>There are several commands in linux to perform different tasks. Here is the list of few commands, based on their use cases :</p>
<h3>Navigation &amp; Structure</h3>
<pre><code class="language-bash">pwd          # Current directory
ls           # List files
cd &lt;dir&gt;     # Move between directories
tree         # Visualize folder structure
</code></pre>
<h3>File Operations</h3>
<pre><code class="language-bash">touch file.txt    # touch command for file creation
mkdir folder      # mkdir for creating directory 
cp file1 file2    # cp command for copying data from one file to another
mv old new        # mv command to move data from old file to new one
rm file           # rm command to delete the file
</code></pre>
<h3>Reading System Files</h3>
<pre><code class="language-bash">cat &lt;file&gt;
less &lt;file&gt;
head &lt;file&gt;
tail -f &lt;file&gt;
</code></pre>
<h3>Searching &amp; Investigation</h3>
<pre><code class="language-bash">find / -name "file"
grep "text" file
locate filename
</code></pre>
<p>There are a lot more commands available in Linux, other then above commands.</p>
<h3>Let's discuss about the findings during the research of linux commands</h3>
<p>The linux file system, is not just storage mechanism or filesystem, but it is a live interface to the Kernel itself.</p>
<h2>Finding 1 : The Routing Table is Just a File</h2>
<p>Path : <code>/proc/net/route</code></p>
<p>The kernel maintains a live routing table, the logic that decides where every outgoing packet goes and exposes it as a plain text file at <code>/proc/net/route</code>. No tool required. No daemon to query. Just a file.</p>
<p>Each row is a route. The columns are hex-encoded: destination, gateway, flags, interface. The system reads this to decide whether a packet should go to the local network or out through the default gateway.</p>
<pre><code class="language-bash">cat /proc/net/route
# Iface  Destination  Gateway   Flags  ...  Mask
# eth0   00000000     0101A8C0  0003        00000000  ← default route → 192.168.1.1
# eth0   0001A8C0     00000000  0001        00FFFFFF  ← local subnet
</code></pre>
<p><code>/proc</code> is not a real disk; it's a virtual filesystem the kernel generates on-the-fly. Reading <code>/proc/net/route</code> is essentially reading a live kernel data structure without any syscall overhead beyond a plain file read.</p>
<h2>Finding 2 : DNS Is Not the First Stop</h2>
<p>Path: <code>/etc/nsswitch.conf</code></p>
<p>Many people assume that when you type a hostname, Linux immediately fires a DNS query. But it doesn't. The actual resolution order is controlled by <code>/etc/nsswitch.conf</code>, the Name Service Switch configuration. One line controls everything :</p>
<pre><code class="language-bash">
hosts: files dns mdns4_minimal
</code></pre>
<p>This means: check <code>/etc/hosts</code> first, then DNS, then mDNS. Before a single DNS packet leaves your machine, the kernel checks the local hosts file. This is why sysadmins can override any domain locally add an entry to <code>/etc/hosts</code> and it wins over DNS every time, unless nsswitch is reconfigured.</p>
<p><strong>Security implication:</strong> Malware sometimes modifies <code>/etc/hosts</code> to redirect banking domains to phishing IPs. Since <code>files</code> comes before <code>dns</code> in the default config, this works silently, without touching any DNS server, without any network anomaly to detect.</p>
<h2>Finding 3 : Every Process Keeps Its Open Files</h2>
<p>Path: <code>/proc/[pid]/fd/</code></p>
<p>Every running process has a directory at <code>/proc/[pid]/fd/</code> containing symbolic links, one for each open file descriptor. This includes open log files, sockets, pipes, devices, and config files.</p>
<pre><code class="language-bash">ls -la /proc/$(pgrep nginx)/fd
# 0 → /dev/null
# 1 → /dev/null
# 4 → socket:[38291]
# 5 → /var/log/nginx/access.log
</code></pre>
<p><strong>What's remarkable :</strong> if a process opens a file and that file is then deleted from disk, the process still holds the file descriptor open. The file's data survives on disk, invisible from the directory tree, but still readable via <code>/proc/[pid]/fd/[n]</code>.</p>
<p><strong>The ghost file phenomenon:</strong> This is a known disk space recovery trick. If <code>df</code> shows a disk is full but <code>du</code> shows low usage, a deleted-but-still-open log file is silently holding the space. You can truncate it via its fd path and reclaim the space without killing the process. The file is gone from the directory, but alive in <code>/proc</code>.</p>
<h2>Finding 4 : Privilege Is Just a Text File</h2>
<p>Path: <code>/etc/sudoers</code></p>
<p>The entire privilege escalation model of Linux rests on a single text file. <code>/etc/sudoers</code> defines exactly who can run what as whom. Its syntax is precise and unforgiving, a mistake here can lock out all admin access permanently.</p>
<pre><code class="language-bash">root    ALL=(ALL:ALL) ALL
%sudo   ALL=(ALL:ALL) ALL

# This line lets the "deploy" user restart nginx without a password:
deploy  ALL=(root) NOPASSWD: /bin/systemctl restart nginx
</code></pre>
<p>The <code>NOPASSWD</code> directive is powerful for automation, but catastrophic if misconfigured. A wildcard like <code>NOPASSWD: ALL</code> on a service account is functionally equivalent to giving that account root access without any authentication.</p>
<h2>Finding 5 : One File Turns Linux Box Into a Router</h2>
<p>Path: <code>/proc/sys/net/ipv4/ip_forward</code></p>
<p>There is a single file that controls whether Linux will forward network packets between interfaces, the defining behavior of a router. It contains either <code>0</code> or <code>1</code>.</p>
<pre><code class="language-bash">cat /proc/sys/net/ipv4/ip_forward
0   # not routing

echo 1 &gt; /proc/sys/net/ipv4/ip_forward
# Now this machine forwards packets between interfaces.
# Combined with iptables NAT rules → full router or VPN gateway.
</code></pre>
<p>VPNs, Docker networking, Kubernetes pod routing, and NAT gateways all depend on this being set to 1. Every container platform enables this silently at startup, through a single write to a single file.</p>
<h2>Finding 6 : How the OS Finds Shared Libraries</h2>
<p><strong>Path:</strong> <code>/etc/</code><a href="http://ld.so"><code>ld.so</code></a><code>.conf</code> <strong>and</strong> <code>/etc/</code><a href="http://ld.so"><code>ld.so</code></a><code>.cache</code></p>
<p>When a program launches, the dynamic linker needs to find <code>.so</code> shared library files. The directories it searches are listed in <code>/etc/</code><a href="http://ld.so"><code>ld.so</code></a><code>.conf</code> and files inside <code>/etc/</code><a href="http://ld.so"><code>ld.so</code></a><code>.conf.d/</code>.</p>
<p>These are compiled into a fast binary cache at <code>/etc/</code><a href="http://ld.so"><code>ld.so</code></a><code>.cache</code> by running <code>ldconfig</code>.</p>
<pre><code class="language-bash">cat /etc/ld.so.conf.d/x86_64-linux-gnu.conf
/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu
</code></pre>
<p><strong>The</strong> <code>LD_PRELOAD</code> <strong>hijacking attack:</strong> The <code>LD_PRELOAD</code> environment variable forces a library to load before anything else, overriding the standard library search entirely. Attackers use this to intercept system calls at the libc level. Classic rootkits used <code>LD_PRELOAD</code> to hide processes from <code>ps</code> by overriding the very libc functions used to enumerate them. The process was running; <code>ps</code> just never saw it.</p>
<h2>Finding 7 : The Auth Log Knows Everything</h2>
<p>Path: <code>/var/log/auth.log</code></p>
<p>The auth log knows everything about who came in.</p>
<p>Every authentication event, successful login, failed login, sudo usage, SSH key acceptance, is written to <code>/var/log/auth.log</code> (on Debian/Ubuntu; <code>/var/log/secure</code> on RHEL/CentOS). It is the system's silent witness.</p>
<pre><code class="language-bash">Apr 22 03:14:22 sshd[2891]: Failed password for root from 45.33.32.156 port 43212 ssh2
Apr 22 03:14:23 sshd[2891]: Failed password for root from 45.33.32.156 port 43212 ssh2
Apr 22 09:01:11 sudo:  alice : TTY=pts/1 ; USER=root ; COMMAND=/bin/cat /etc/shadow
</code></pre>
<p>That last line is alarming: <code>alice</code> used sudo to read <code>/etc/shadow</code> the file containing all password hashes. Auth logs are the first place to check after any suspected breach.</p>
<h2>Finding 8 : Scheduled Tasks Are Scattered Across the Filesystem</h2>
<p>Paths: <code>/etc/cron.d/</code> · <code>/etc/cron.daily/</code> · <code>/var/spool/cron/crontabs/</code></p>
<p>Most people know about <code>crontab -e</code>. What they don't realize is that cron jobs live in at least four different locations. Package managers drop cron jobs in <code>/etc/cron.d/</code>. The system runs daily/weekly/monthly scripts from <code>/etc/cron.daily/</code>, <code>/etc/cron.weekly/</code>, and so on. User-specific crontabs live in <code>/var/spool/cron/crontabs/[username]</code>.</p>
<pre><code class="language-bash">ls /etc/cron.d/
# certbot   e2scrub_all   php   sysstat

cat /etc/cron.d/certbot
# 0 */12 * * * root certbot renew -q
</code></pre>
<p>Certbot silently auto-renews your TLS certificates every 12 hours, a cron job you probably never set up yourself, living in a directory you may never check.</p>
<h2>Finding 9 : Devices That Aren't Physical</h2>
<p>Path: <code>/dev/null</code>, <code>/dev/zero</code>, <code>/dev/random</code></p>
<p>The <code>/dev</code> directory contains device files, but not all of them represent hardware. Three of the most useful are entirely virtual, implemented purely in kernel code.</p>
<p><code>/dev/null</code> is the black hole. Anything written to it is discarded. Reading from it returns EOF immediately. It exists to silence output you don't care about.</p>
<p><code>/dev/zero</code> produces an infinite stream of zero bytes. It's used to create empty files of exact sizes, <code>dd if=/dev/zero of=disk.img bs=1M count=100</code> creates a precise 100MB blank file, useful for disk image creation and benchmarking.</p>
<p><code>/dev/random</code> and <code>/dev/urandom</code> are sources of cryptographically random bytes, fed by entropy gathered from hardware events: keystrokes, disk I/O timing, network packet arrival. Every TLS key, SSH key, and cryptographic token generated on Linux is seeded from here.</p>
<h2>Finding 10 : Reading Live TCP Connections Without Any Tool</h2>
<p>Path: <code>/proc/net/tcp</code></p>
<p>Here is something that genuinely surprised me: <code>netstat</code> and <code>ss</code> have no special kernel access. They are just reading <code>/proc/net/tcp</code> , a file that lists every active TCP socket in the kernel right now, in plain text. The tools just decode it for you.</p>
<pre><code class="language-bash">cat /proc/net/tcp
#  sl  local_address  rem_address  st  ...  inode
   0:  00000000:0016  00000000:0000  0A  ...  12938   ← LISTEN on port 22 (SSH)
   1:  0F02000A:0016  0202000A:C4E2  01  ...  18342   ← ESTABLISHED connection
</code></pre>
<p>The addresses are little-endian hex. <code>0016</code> hex = <code>22</code> decimal — that's SSH. State <code>0A</code> = LISTEN. State <code>01</code> = ESTABLISHED. The <code>inode</code> column links the socket back to a specific process via <code>/proc/[pid]/fd/</code>.</p>
<p>Decoding the address manually:</p>
<pre><code class="language-bash"># 0F02000A → bytes reversed: 0A 00 02 0F → 10.0.2.15
printf '%d.%d.%d.%d\n' 0x0A 0x00 0x02 0x0F
# 10.0.2.15
</code></pre>
<h2>Conclusion</h2>
<p>The deeper insight from this investigation is architectural. Linux exposes its own internals as files. Routing tables, process state, socket connections, kernel tunables, all of it is readable, and sometimes writable, through the filesystem. This is not accidental. It is the Unix philosophy made real: everything is a file, and files can be read.</p>
<p>If you understand the filesystem, you understand the system. You don't need a monitoring tool if you can read <code>/proc</code>. You don't need a network scanner if you can parse <code>/proc/net/tcp</code>. The OS is already telling you everything, you just need to know where to look.</p>
]]></content:encoded></item><item><title><![CDATA[Spread vs Rest Operators in JavaScript]]></title><description><![CDATA[The spread and rest operators are powerful features introduced in ES6 that use the same syntax (...) but serve completely different purposes.
Both are written with three dots ... which is exactly why ]]></description><link>https://blog.rohitchornele.online/spread-vs-rest-operators-in-javascript</link><guid isPermaLink="true">https://blog.rohitchornele.online/spread-vs-rest-operators-in-javascript</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[ChaiCohort]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Spread operator]]></category><category><![CDATA[Rest operator]]></category><category><![CDATA[REST]]></category><dc:creator><![CDATA[Rohit Chornele]]></dc:creator><pubDate>Thu, 26 Mar 2026 17:51:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6688fdd59dfed4afe8f5b269/01fbd9ba-fb2f-41db-85e5-d1da50c4856a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The spread and rest operators are powerful features introduced in ES6 that use the same syntax (<code>...</code>) but serve completely different purposes.</p>
<p>Both are written with three dots <code>...</code> which is exactly why they confuse so many people. They look identical. But they do opposite things depending on where and how you use them. One expands values out, the other collects values in. Once you internalize that contrast, the two become very easy to tell apart.</p>
<blockquote>
<p><strong>Spread = Expands values</strong></p>
<p><strong>Rest = Collects values</strong></p>
</blockquote>
<h3><strong>Why These Operators Are Important</strong></h3>
<p>They help:</p>
<ul>
<li><p>Simplify code</p>
</li>
<li><p>Handle data easily</p>
</li>
<li><p>Improve readability</p>
</li>
</ul>
<h2>1. What the Spread Operator Does</h2>
<p>The spread operator takes an array or object and expands it into individual elements out into a new context.</p>
<p>Think of it like unpacking a suitcase: you take everything that was bundled together and lay each item out separately.</p>
<pre><code class="language-javascript">const fruits = ['apple', 'banana', 'mango'];

// spread operator
console.log(...fruits); // apple banana mango
//         ↑ spread unpacks the array into three separate values
</code></pre>
<p>Instead of passing the whole array as one thing, spread breaks it apart and hands over each element individually. This becomes very useful when you need to pass array items as separate arguments to a function.</p>
<pre><code class="language-javascript">const numbers = [4, 1, 7, 2];

console.log(Math.max(...numbers)); // 7
// Math.max doesn't accept an array — it needs individual values
// spread converts [4, 1, 7, 2] into Math.max(4, 1, 7, 2)
</code></pre>
<p>Without spread, you'd have to manually write <code>Math.max(4, 1, 7, 2)</code> or use an older workaround like <code>.apply()</code>. Spread makes this elegant and readable.</p>
<h2>2. What the Rest Operator Does</h2>
<p>The rest operator does the exact opposite, it <strong>collects</strong> multiple individual values and bundles them together into a single array. <strong>If spread is unpacking a suitcase, rest is <em>packing</em> one.</strong></p>
<p>The most common place you'll see rest is in function parameters, where it gathers all the extra arguments passed into a function:</p>
<pre><code class="language-javascript">function sum(...numbers) {
  // `numbers` is now an array of everything passed in
  return numbers.reduce((total, n) =&gt; total + n, 0);
}

sum(1, 2, 3);       // 6
sum(10, 20, 30, 40); // 100
</code></pre>
<p>Here, no matter how many arguments you pass to <code>sum</code>, the rest operator collects all of them into the <code>numbers</code> array. The function doesn't need to know in advance how many values it will receive, rest handles that flexibility for you.</p>
<h2>3. The Difference Between Spread and Rest</h2>
<p>Even though they share the same <code>...</code> syntax, the key to telling them apart is asking: is this expanding values out, or collecting values in?</p>
<p>Spread appears where <strong>values are being used</strong>, in function calls, array literals, or object literals. It takes something bundled and spreads it open. Rest appears where <strong>parameters or variables are being defined</strong>, in function signatures or destructuring. It takes loose individual values and wraps them up.</p>
<p>A side-by-side comparison makes this very clear:</p>
<pre><code class="language-javascript">// SPREAD — expanding an array into a function call
const nums = [1, 2, 3];
console.log(Math.max(...nums)); // spread at the call site

// REST — collecting arguments inside a function definition
function add(...nums) {        // rest in the parameter list
  return nums.reduce((a, b) =&gt; a + b, 0);
}
</code></pre>
<p>Both lines use <code>...nums</code>, but the first is spreading outward and the second is collecting inward. The position call site vs. definition, is what tells you which one it is.</p>
<h2>4. Using Spread with Arrays and Objects</h2>
<p>Spread really shines when working with arrays and objects, particularly for creating copies and combining data without mutating the originals.</p>
<h3><strong>Copying an array</strong> without affecting the original:</h3>
<pre><code class="language-js">const original = [1, 2, 3];
const copy = [...original]; // a fresh, independent array

copy.push(4);
console.log(original); // [1, 2, 3] — untouched
console.log(copy);     // [1, 2, 3, 4]
</code></pre>
<p>This is important because in JavaScript, assigning an array directly (<code>const copy = original</code>) doesn't create a copy — both variables point to the same array. Spread gives you a true, independent copy.</p>
<h3><strong>Merging arrays</strong> is equally clean:</h3>
<pre><code class="language-js">const veggies = ['carrot', 'pea'];
const fruits  = ['apple', 'mango'];

const food = [...veggies, ...fruits, 'rice']; // mix and match freely
// ['carrot', 'pea', 'apple', 'mango', 'rice']
</code></pre>
<p>Spread works just as naturally with <strong>objects</strong>. You can copy or merge objects the same way:</p>
<pre><code class="language-js">const defaults = { theme: 'light', fontSize: 14, language: 'en' };
const userPrefs = { fontSize: 18, language: 'hi' };

// Merge: userPrefs values override defaults where they overlap
const settings = { ...defaults, ...userPrefs };
// { theme: 'light', fontSize: 18, language: 'hi' }
</code></pre>
<p>Notice that <code>fontSize</code> and <code>language</code> from <code>userPrefs</code> overwrite the values from <code>defaults</code>, while <code>theme</code> — which only exists in <code>defaults</code> — is preserved. This pattern of spreading defaults first and then spreading user-provided values on top is extremely common in real codebases.</p>
<h2>5. Practical Use Cases</h2>
<p>Knowing the mechanics is one thing, seeing where these operators actually appear in everyday code is what makes them stick. Adding items to an array without mutating it is a very common need, especially in frameworks like React where you're expected to treat data as immutable:</p>
<pre><code class="language-javascript">const cart = ['shoes', 'shirt'];

// Add an item by creating a new array instead of using push()
const updatedCart = [...cart, 'hat'];
// ['shoes', 'shirt', 'hat'] — cart itself is unchanged
</code></pre>
<p><strong>Passing a dynamic list of arguments</strong> to any function that expects individual values:</p>
<pre><code class="language-javascript">const dates = [2024, 6, 15]; // year, month, day
const birthday = new Date(...dates); // same as new Date(2024, 6, 15)
</code></pre>
<p><strong>Cloning and updating an object in one step</strong>, which you'll see constantly in state management:</p>
<pre><code class="language-javascript">const user = { name: 'Meera', age: 25, city: 'Pune' };

// Update age without mutating the original user object
const updatedUser = { ...user, age: 26 };
// { name: 'Meera', age: 26, city: 'Pune' }
</code></pre>
<p><strong>Building flexible utility functions</strong> using rest, so they can accept any number of arguments:</p>
<pre><code class="language-javascript">function logWithPrefix(prefix, ...messages) { 
    // prefix is one fixed argument, messages collects the rest
    messages.forEach(msg =&gt; console.log([\({prefix}] \){msg})); 
}

logWithPrefix('INFO', 'Server started', 'Listening on port 3000');
// [INFO] Server started
// [INFO] Listening on port 3000
</code></pre>
<p>This kind of function is far more flexible than one that accepts a fixed number of arguments. You can pass two messages or ten, it handles all of them gracefully.</p>
<h2>Conclusion</h2>
<p>Spread and rest are two sides of the same coin. Spread takes a collection and fans it out into individual pieces, useful when you need to pass, copy, or combine data. Rest takes individual pieces and gathers them into a collection, useful when you want a function to handle a variable number of arguments or when you want to capture "the remainder" in a destructuring pattern.</p>
<p>The three dots are the same, but the direction of flow is opposite, and that direction is always determined by context: are you <em>providing</em> values (spread) or <em>receiving</em> them (rest)? Train yourself to ask that question whenever you see <code>...</code>, and the two will never feel confusing again.</p>
]]></content:encoded></item><item><title><![CDATA[Understanding this Keyword in JavaScript]]></title><description><![CDATA[If you've spent any time with JavaScript, you've probably run into this and thought : "okay what is this thing and why does it keep breaking my code?"
You're not alone. this is one of those concepts t]]></description><link>https://blog.rohitchornele.online/understanding-this-keyword-in-javascript</link><guid isPermaLink="true">https://blog.rohitchornele.online/understanding-this-keyword-in-javascript</guid><dc:creator><![CDATA[Rohit Chornele]]></dc:creator><pubDate>Thu, 26 Mar 2026 17:11:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6688fdd59dfed4afe8f5b269/9d4e1b4b-8da8-4b0b-afb3-49cd591f85b5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you've spent any time with JavaScript, you've probably run into <code>this</code> and thought : "okay what is this thing and why does it keep breaking my code?"</p>
<p>You're not alone. <code>this</code> is one of those concepts that feels confusing at first, but once it clicks, you'll wonder why it ever confused you. Let's fix that today.</p>
<p>In simple words : The keyword <code>this</code> refers to the object that is currently calling the function.</p>
<p><strong>“this = who is calling the function”</strong></p>
<p>Once you understand this idea, most of the confusion disappears.</p>
<h2>1. What Does <code>this</code> Represent?</h2>
<p>The value of <code>this</code> depends on <strong>how a function is called</strong>, not where it is written.</p>
<p><code>this</code> is the object that called the function. That's it. Not where the function was defined, not what the function does, purely who <em>ran</em> it. Every confusing behavior of <code>this</code> traces back to this single idea.</p>
<p><strong>Basic Example :</strong></p>
<pre><code class="language-javascript">function show() {
  console.log(this);
}

show(); // global object
</code></pre>
<p>Think of it like the word "home." If you ask Ravi where home is, he'll say Mumbai. Ask Priya the same question and she'll say Delhi. The word "home" is the same, but what it points to depends entirely on who's asking. <code>this</code> works the same way : it's a pointer whose value depends on the context of the call.</p>
<h2>2. <code>this</code> in the Global Context</h2>
<p>When you write code at the top level : outside any function or object, <code>this</code> points to the <strong>global object</strong>. In a browser, that's <code>window</code>. In Node.js, it's <code>global</code>.</p>
<pre><code class="language-javascript">console.log(this);             // Window { ... } in a browser
console.log(this === window);  // true
</code></pre>
<p>You can think of the global context as JavaScript's default home. When no specific object is making the call, <code>this</code> falls back here automatically.</p>
<p>One thing worth knowing early: in <strong>strict mode</strong> (<code>'use strict'</code>), <code>this</code> inside a regular function becomes <code>undefined</code> instead of pointing to the global object. This is a deliberate safety feature to stop you from accidentally creating or modifying global variables when you didn't intend to. You'll encounter strict mode often in modern JavaScript, so it's good to keep this in the back of your mind.</p>
<h2>3. <code>this</code> Inside Objects</h2>
<p>This is where <code>this</code> stops being abstract and starts being genuinely useful. When a function is a method on an object and you call it through that object, <code>this</code> points to the object itself.</p>
<pre><code class="language-javascript">const person = {
  name: 'Arjun',
  greet: function() {
    // `this` is `person`, because person is the one calling greet()
    console.log('Hello, I am ' + this.name);
  }
};

person.greet(); // Hello, I am Arjun
</code></pre>
<p>Here's a practical trick to always get this right: <strong>look at what's to the left of the dot at the call site.</strong> Whatever object you see there is what <code>this</code> will be inside the function. <code>person.greet()</code>, <code>person</code> is to the left, so <code>this</code> is <code>person</code>.</p>
<h2>4. <code>this</code> Inside Functions</h2>
<p>Here's where most people hit their first real wall with <code>this</code>, so let's walk through it carefully.</p>
<p>If you take a method off an object and call it as a plain, standalone function, it <strong>loses its context</strong>. There's no longer an object to the left of the dot, so <code>this</code> reverts to the global object (or <code>undefined</code> in strict mode).</p>
<p>js</p>
<pre><code class="language-javascript">const person = {
  name: 'Priya',
  greet: function() {
    console.log('Hello, I am ' + this.name);
  }
};

const sayHello = person.greet;  // detached — just a reference to the function

sayHello();  // Hello, I am undefined  ← `this` is now window, not person
</code></pre>
<p>When you assigned <code>person.greet</code> to <code>sayHello</code>, you only copied the function reference, you didn't carry the object along with it. So when <code>sayHello()</code> runs, JavaScript looks for a caller to the left of the dot, finds nothing, and defaults to global. Since <a href="http://window.name"><code>window.name</code></a> doesn't exist in your code, you get <code>undefined</code>.</p>
<h3><code>this</code> inside Arrow Functions :</h3>
<p><strong>Arrow functions</strong> are the clean solution to this. Unlike regular functions, an arrow function doesn't have its own <code>this</code> at all — it simply inherits <code>this</code> from wherever it was <em>written</em> (its surrounding scope). This means it locks in the value of <code>this</code> at definition time, not call time.</p>
<pre><code class="language-javascript">const user = {
  name: 'Kiran',
  sayHi: function() {
    // Arrow function inherits `this` from sayHi(), where `this` is `user`
    setTimeout(() =&gt; {
      console.log('Hi, ' + this.name);  // Hi, Kiran ✓
    }, 500);
  }
};

user.sayHi();
</code></pre>
<p>The arrow function inside <code>setTimeout</code> looks outward to <code>sayHi()</code>'s scope to find <code>this</code>, and since <code>sayHi</code> was called as <code>user.sayHi()</code>, <code>this</code> there is <code>user</code>. Problem solved.</p>
<h2>5. How the Calling Context Changes <code>this</code></h2>
<p>JavaScript gives you three built-in methods : <code>call()</code>, <code>apply()</code>, and <code>bind()</code> , to take manual control of <code>this</code>. Think of them as tools for saying "run this function, but pretend <em>this specific object</em> called it."</p>
<p><code>call()</code> invokes the function immediately with a <code>this</code> you choose:</p>
<pre><code class="language-javascript">function introduce() {
  console.log('Hi, I am ' + this.name);
}

const user1 = { name: 'Ravi' };
const user2 = { name: 'Meera' };

introduce.call(user1);  // Hi, I am Ravi
introduce.call(user2);  // Hi, I am Meera
</code></pre>
<p><code>apply()</code> does exactly the same thing, but you pass any extra arguments as an array rather than individually. Functionally, <code>call</code> and <code>apply</code> are nearly identical, the only difference is that syntax detail.</p>
<p><code>bind()</code> is different in one important way: instead of calling the function immediately, it returns a <em>new</em> function that is permanently locked to the <code>this</code> you specify, no matter how or where it gets called later.</p>
<pre><code class="language-javascript">function introduce() {
  console.log('Hi, I am ' + this.name);
}

const greetAsRavi = introduce.bind({ name: 'Ravi' });

greetAsRavi();          // Hi, I am Ravi — always, no matter what
greetAsRavi.call({ name: 'Someone Else' });  // Still: Hi, I am Ravi
</code></pre>
<p><code>bind()</code> is especially valuable when you're passing a method as a callback, situations where you <em>know</em> the function will lose its context. Instead of relying on arrow functions or workarounds, you can just bind it upfront and trust it'll always have the right <code>this</code>.</p>
<h2>Conclusion</h2>
<p>At its core, <code>this</code> comes down to one question you should ask every time you see it: <em>who is calling this function right now?</em> Follow the dot at the call site, trace the caller, and <code>this</code> almost always makes perfect sense. Global code defaults to the global object, object methods point back to the object, detached functions lose their context, and arrow functions simply inherit <code>this</code> from wherever they were written. When you need full control, <code>call</code>, <code>apply</code>, and <code>bind</code> let you set the caller yourself.</p>
<p>What makes <code>this</code> feel tricky at first is that the same function can behave differently depending on <em>how</em> it's invoked, not how it's written. That flexibility is actually what makes <code>this</code> so powerful, one reusable function can work correctly across many different objects just by calling it the right way.</p>
]]></content:encoded></item><item><title><![CDATA[Map and Set in JavaScript]]></title><description><![CDATA[Map and Set in JavaScript are modern data structures introduced in ES6 to solve common problems developers face when working with objects and arrays.
While objects and arrays are powerful, they have l]]></description><link>https://blog.rohitchornele.online/map-and-set-in-javascript</link><guid isPermaLink="true">https://blog.rohitchornele.online/map-and-set-in-javascript</guid><category><![CDATA[ChaiCode]]></category><category><![CDATA[ChaiCohort]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[map]]></category><category><![CDATA[Sets]]></category><dc:creator><![CDATA[Rohit Chornele]]></dc:creator><pubDate>Thu, 26 Mar 2026 16:32:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6688fdd59dfed4afe8f5b269/e305fe52-dc04-40b1-95e7-d98f552cb4bb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Map and Set in JavaScript are modern data structures introduced in ES6 to solve common problems developers face when working with objects and arrays.</p>
<p>While objects and arrays are powerful, they have limitations when it comes to handling key-value pairs and unique data. That’s where <code>Map</code> and <code>Set</code> come in—they provide cleaner, more efficient ways to manage data.</p>
<p>They're not replacements for objects and arrays, they're specialized tools that do certain jobs significantly better.</p>
<p>This article will show you exactly what those jobs are.</p>
<h2>1. What Map Is ?</h2>
<p>A Map is a collection of <strong>key-value pairs</strong>, just like an object.</p>
<p>The critical difference: <strong>Map accepts any value as a key.</strong> Numbers, objects, booleans, even other Maps. Objects only support strings and symbols as keys.</p>
<p><strong>Creating and using a Map:</strong></p>
<pre><code class="language-javascript">let userRoles = new Map();

userRoles.set("priya", "admin");
userRoles.set("rahul", "editor");
userRoles.set("ananya", "viewer");

console.log(userRoles.get("priya"));   // "admin"
console.log(userRoles.has("rahul"));   // true
console.log(userRoles.size);           // 3

userRoles.delete("ananya");
console.log(userRoles.size);           // 2
</code></pre>
<p>Notice the clean API : <code>.set()</code>, <code>.get()</code>, <code>.has()</code>, <code>.delete()</code>, <code>.size</code>. Everything is explicit and purpose-built, unlike objects where you use <code>obj.key</code>, <code>delete obj.key</code>, and <code>Object.keys(obj).length</code>.</p>
<h2>2. What Set Is ?</h2>
<p>A Set is a collection of <strong>unique values</strong>. Add the same value twice, it only appears once. That's the defining characteristic, and it's the whole reason Set exists.</p>
<pre><code class="language-js">let tags = new Set();

tags.add("javascript");
tags.add("frontend");
tags.add("javascript");  // duplicate — silently ignored
tags.add("es6");

console.log(tags.size);  // 3 — not 4
console.log(tags);       // Set { "javascript", "frontend", "es6" }
</code></pre>
<p>No error on duplicates. No fuss. They're just ignored.</p>
<p><strong>Common Set operations:</strong></p>
<pre><code class="language-javascript">let skills = new Set(["html", "css", "javascript", "css", "html"]);

console.log(skills.size);              // 3 — duplicates removed automatically
console.log(skills.has("javascript")); // true
console.log(skills.has("python"));     // false

skills.add("react");
skills.delete("html");

console.log([...skills]);  // ["css", "javascript", "react"]
</code></pre>
<p><strong>The most practical use : removing duplicates from an array:</strong></p>
<pre><code class="language-javascript">let rawTags = ["javascript", "css", "javascript", "react", "css", "html"];

let uniqueTags = [...new Set(rawTags)];

console.log(uniqueTags);
// ["javascript", "css", "react", "html"]
</code></pre>
<p>One line. No loops, no filters, no manual checking. Create a Set (duplicates removed automatically), spread it back into an array.</p>
<p><strong>Iterating a Set:</strong></p>
<pre><code class="language-javascript">let categories = new Set(["books", "electronics", "clothing"]);

for (let category of categories) {
  console.log(category);
}
// books
// electronics
// clothing
</code></pre>
<h2>3. Map vs Object</h2>
<p>Both store key-value pairs. Here's where they diverge in ways that actually matter:</p>
<p><strong>Key types:</strong></p>
<pre><code class="language-javascript">// Object — keys are always strings (or symbols)
let obj = {};
obj[1] = "one";
obj[true] = "yes";

console.log(Object.keys(obj));  // ["1", "true"] — converted to strings

// Map — keys keep their actual type
let map = new Map();
map.set(1, "one");
map.set(true, "yes");

console.log([...map.keys()]);  // [1, true] — kept as number and boolean
</code></pre>
<p><strong>Size:</strong></p>
<pre><code class="language-javascript">let obj = { a: 1, b: 2, c: 3 };
let map = new Map([["a", 1], ["b", 2], ["c", 3]]);

// Object — no built-in size
console.log(Object.keys(obj).length);  // 3 — manual calculation

// Map — built-in
console.log(map.size);  // 3 — direct property
</code></pre>
<p><strong>Iteration:</strong></p>
<pre><code class="language-javascript">// Object — needs Object.entries(), not directly iterable
for (let [key, value] of Object.entries(obj)) {
  console.log(key, value);
}

// Map — directly iterable
for (let [key, value] of map) {
  console.log(key, value);
}
</code></pre>
<p><strong>Prototype pollution risk:</strong></p>
<p>Plain objects inherit from <code>Object.prototype</code>. This means they come with built-in properties like <code>toString</code>, <code>hasOwnProperty</code>, and <code>constructor</code>. These can cause subtle bugs if you're not careful with key names:</p>
<pre><code class="language-javascript">let permissions = {};
permissions["admin"] = true;
permissions["toString"] = true;  // shadows Object.prototype.toString

// Now toString is broken on this object
console.log(permissions.toString());  // "true" — not the function anymore
</code></pre>
<p>Map has no such issue. It has no inherited prototype properties that could conflict with your data.</p>
<h3><strong>Side-by-side comparison:</strong></h3>
<table>
<thead>
<tr>
<th></th>
<th>Object</th>
<th>Map</th>
</tr>
</thead>
<tbody><tr>
<td>Key types</td>
<td>Strings / Symbols only</td>
<td>Any value</td>
</tr>
<tr>
<td>Size</td>
<td>Manual (<code>Object.keys().length</code>)</td>
<td><code>.size</code> property</td>
</tr>
<tr>
<td>Iteration</td>
<td>Via <code>Object.entries()</code></td>
<td>Directly iterable</td>
</tr>
<tr>
<td>Insertion order</td>
<td>Not guaranteed (older JS)</td>
<td>Always preserved</td>
</tr>
<tr>
<td>Prototype risk</td>
<td>Yes</td>
<td>No</td>
</tr>
<tr>
<td>Best for</td>
<td>Structured records, config</td>
<td>Dynamic key-value storage</td>
</tr>
</tbody></table>
<h2>4. Set vs Array</h2>
<p>Both hold collections of values. The difference is purpose, arrays are ordered lists that allow duplicates; Sets are collections that guarantee uniqueness.</p>
<p><strong>Duplicate behavior:</strong></p>
<pre><code class="language-javascript">let arr = [1, 2, 2, 3, 3, 3];
console.log(arr.length);  // 6 — keeps duplicates

let set = new Set([1, 2, 2, 3, 3, 3]);
console.log(set.size);    // 3 — removes duplicates
</code></pre>
<p><strong>Membership checking:</strong></p>
<pre><code class="language-javascript">let arr = ["apple", "banana", "mango"];
let set = new Set(["apple", "banana", "mango"]);

// Array — scans the whole array O(n)
console.log(arr.includes("mango"));  // true

// Set — direct lookup O(1)
console.log(set.has("mango"));       // true
</code></pre>
<p>For large collections, this performance difference is significant. If you're frequently checking whether a value exists, Set is dramatically faster than an array.</p>
<p><strong>What arrays can do that Set can't:</strong></p>
<pre><code class="language-javascript">let arr = [1, 2, 3, 4, 5];

// Index access
console.log(arr[2]);  // 3

// map, filter, reduce
let doubled = arr.map(x =&gt; x * 2);

// Duplicates (when you want them)
let repeated = [1, 1, 2, 2, 3];
</code></pre>
<p>Sets don't support index access <code>set[0]</code> gives you <code>undefined</code>. They also don't have <code>map</code>, <code>filter</code>, or <code>reduce</code> directly. For those operations, convert to an array first:</p>
<pre><code class="language-javascript">let set = new Set([1, 2, 3, 4, 5]);
let doubled = [...set].map(x =&gt; x * 2);
// [2, 4, 6, 8, 10]
</code></pre>
<h3><strong>Side-by-side comparison:</strong></h3>
<table>
<thead>
<tr>
<th></th>
<th>Array</th>
<th>Set</th>
</tr>
</thead>
<tbody><tr>
<td>Duplicates</td>
<td>Allowed</td>
<td>Not allowed</td>
</tr>
<tr>
<td>Index access</td>
<td>Yes (<code>arr[0]</code>)</td>
<td>No</td>
</tr>
<tr>
<td>Has <code>.map/.filter</code></td>
<td>Yes</td>
<td>No (convert first)</td>
</tr>
<tr>
<td>Membership check</td>
<td><code>includes()</code> — O(n)</td>
<td><code>has()</code> — O(1)</td>
</tr>
<tr>
<td>Order preserved</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>Best for</td>
<td>Ordered lists, transformations</td>
<td>Unique collections, lookup</td>
</tr>
</tbody></table>
<h2>5. When to Use Map and Set</h2>
<p>The clearest signal for reaching for Map or Set is when you find yourself working around a limitation of plain objects or arrays. Use Map when: You need non-string keys, especially when you want to associate data with DOM elements or objects:</p>
<pre><code class="language-javascript">let elementData = new Map();

let button = document.getElementById("submit");
let input  = document.getElementById("email");

elementData.set(button, { clickCount: 0, lastClicked: null });
elementData.set(input,  { errorCount: 0, lastError: null });
</code></pre>
<p>You need to know the size directly, or iterate keys and values frequently:</p>
<pre><code class="language-javascript">let config = new Map([
  ["theme", "dark"],
  ["language", "en"],
  ["timezone", "IST"]
]);

console.log(`${config.size} settings loaded`);

for (let [key, value] of config) {
  applyConfig(key, value);
}
</code></pre>
<p>The data is highly dynamic, keys being added and removed frequently:</p>
<pre><code class="language-javascript">let activeSessions = new Map();

function login(userId, token) {
  activeSessions.set(userId, { token, loginTime: Date.now() });
}

function logout(userId) {
  activeSessions.delete(userId);
}

function isActive(userId) {
  return activeSessions.has(userId);
}
</code></pre>
<p><strong>Use Set when:</strong></p>
<p>You're collecting values and don't want duplicates:</p>
<pre><code class="language-javascript">// Collecting unique error codes from multiple API calls
let errorCodes = new Set();

responses.forEach(response =&gt; {
  if (response.error) errorCodes.add(response.error.code);
});

console.log([...errorCodes]);  // only unique error codes
</code></pre>
<p>You need fast membership checking over a large list:</p>
<pre><code class="language-javascript">// Blocklist lookup — Set is much faster than array for this
let blockedUsers = new Set(["user_42", "user_99", "user_187"]);

function canPost(userId) {
  return !blockedUsers.has(userId);
}
</code></pre>
<p>You want to find the union, intersection, or difference of two collections:</p>
<pre><code class="language-js">let setA = new Set([1, 2, 3, 4]);
let setB = new Set([3, 4, 5, 6]);

// Union — all values from both
let union = new Set([...setA, ...setB]);
// Set { 1, 2, 3, 4, 5, 6 }

// Intersection — only values in both
let intersection = new Set([...setA].filter(x =&gt; setB.has(x)));
// Set { 3, 4 }

// Difference — values in A but not B
let difference = new Set([...setA].filter(x =&gt; !setB.has(x)));
// Set { 1, 2 }
</code></pre>
<p>These patterns come up in real features, finding common friends, shared tags, users who belong to one group but not another.</p>
<h2>Conclusion</h2>
<p>Map and Set aren't replacements for objects and arrays. They're specialized tools that solve specific problems cleanly.</p>
<p>Reach for <strong>Map</strong> when your keys aren't strings, when you need reliable size and iteration, or when data is dynamic enough that an object's prototype quirks could be a problem.</p>
<p>Reach for <strong>Set</strong> when uniqueness matters, when you need fast membership checking, or when you want to perform set operations like union and intersection cleanly.</p>
]]></content:encoded></item></channel></rss>