<?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[🧊 GaurangPods]]></title><description><![CDATA[I believe the thoughtful use of technology quietly improves lives, and that belief fuels everything I build and explore 💻. Whatever I learn during this exploration, I try to share it here so others can benefit from it. I’m fascinated by how technology empowers people, businesses, and startups.]]></description><link>https://blogs.gaurangpods.com</link><generator>RSS for Node</generator><lastBuildDate>Sat, 09 May 2026 22:46:43 GMT</lastBuildDate><atom:link href="https://blogs.gaurangpods.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[REST API Design Made Simple with Express.js]]></title><description><![CDATA[If you’ve started backend development recently, chances are you’ve already heard the term REST API being used everywhere. Whether you’re building authentication systems, social media platforms, e-comm]]></description><link>https://blogs.gaurangpods.com/rest-api-design-express-js</link><guid isPermaLink="true">https://blogs.gaurangpods.com/rest-api-design-express-js</guid><category><![CDATA[Express]]></category><category><![CDATA[api]]></category><category><![CDATA[APIs]]></category><category><![CDATA[backend]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Gaurang Nagar]]></dc:creator><pubDate>Sat, 09 May 2026 19:40:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950f282d7c55cc3d6748277/163b1d84-a38e-40fc-b1fa-2b3dae6195d7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you’ve started backend development recently, chances are you’ve already heard the term REST API being used everywhere. Whether you’re building authentication systems, social media platforms, e-commerce applications, or dashboards, REST APIs become one of the core parts of backend communication. Initially, terms like routes, resources, HTTP methods, status codes, and endpoints may feel slightly confusing because many concepts appear together at once. But honestly, the core idea behind REST APIs is actually very simple once you understand how client-server communication works.<br />At a very basic level, APIs allow the frontend and backend to communicate with each other. Whenever a frontend application needs data, it sends a request to the backend server, and the backend responds with the required information. REST APIs simply provide a structured and organized way of handling this communication.</p>
<p>In this blog, we’ll understand what REST APIs actually are, what resources mean in REST architecture, how HTTP methods work, what status codes represent, and how to design cleaner routes in Express.js using proper REST principles.</p>
<h3>What REST API Actually Means</h3>
<p>REST stands for Representational State Transfer. The name sounds complicated initially, but in practice REST APIs are mainly about designing backend routes in a clean and predictable way.<br />A REST API allows clients and servers to communicate using HTTP requests. The client sends a request, the server processes it, and then the server sends back a response.</p>
<p>For example:</p>
<pre><code class="language-javascript">GET /users
</code></pre>
<p>This request may ask the server to return all users.</p>
<p>Similarly:</p>
<pre><code class="language-javascript">POST /users
</code></pre>
<p>This request may ask the server to create a new user.<br />The main idea behind REST is keeping routes structured around resources instead of random route naming.</p>
<h3>Understanding Resources in REST APIs</h3>
<p>Resources are one of the most important concepts in REST architecture.<br />A resource simply means the main data entity your API is working with.<br />Examples:</p>
<ul>
<li><p>users</p>
</li>
<li><p>products</p>
</li>
<li><p>posts</p>
</li>
<li><p>orders</p>
</li>
<li><p>comments</p>
</li>
</ul>
<p>Suppose you are building a social media backend. In that case, users and posts may become resources.</p>
<p>Instead of creating routes like:</p>
<pre><code class="language-javascript">/getAllUsers
</code></pre>
<p>REST principles usually prefer cleaner resource-based routes like:</p>
<pre><code class="language-javascript">/users
</code></pre>
<p>This makes APIs easier to understand and maintain later.</p>
<h3>Understanding HTTP Methods</h3>
<p>REST APIs heavily use HTTP methods for defining actions. Instead of creating separate route names for every operation, REST combines routes with HTTP methods to describe behavior.<br />The four most common methods are:</p>
<ul>
<li><p>GET</p>
</li>
<li><p>POST</p>
</li>
<li><p>PUT</p>
</li>
<li><p>DELETE</p>
</li>
</ul>
<p>These methods directly map to CRUD operations.</p>
<h3>GET Request</h3>
<p>GET is used for fetching data from the server.</p>
<p>Example:</p>
<pre><code class="language-javascript">GET /users
</code></pre>
<p>This may return all users.</p>
<p>Another example:</p>
<pre><code class="language-javascript">GET /users/101
</code></pre>
<p>This may return a specific user having ID <code>101</code>.</p>
<p>In Express.js:</p>
<pre><code class="language-javascript">app.get("/users", (req, res) =&gt; {
  res.send("All users fetched");
});
</code></pre>
<p>GET requests are mainly used whenever the client wants to retrieve data.</p>
<h3>POST Request</h3>
<p>POST is used for creating new resources.</p>
<p>Example:</p>
<pre><code class="language-javascript">POST /users
</code></pre>
<p>This may create a new user in the database.<br />Express example:</p>
<pre><code class="language-javascript">app.post("/users", (req, res) =&gt; {
  res.send("User created");
});
</code></pre>
<p>POST requests usually carry data inside the request body.</p>
<h3>PUT Request</h3>
<p>PUT is used for updating existing resources.<br />Example:</p>
<pre><code class="language-javascript">PUT /users/101
</code></pre>
<p>This may update the user having ID <code>101</code>.</p>
<p>Express example:</p>
<pre><code class="language-javascript">app.put("/users/:id", (req, res) =&gt; {
  res.send("User updated");
});
</code></pre>
<p>PUT requests are commonly used for editing or replacing existing data.</p>
<h3>DELETE Request</h3>
<p>DELETE is used for removing resources.</p>
<p>Example:</p>
<pre><code class="language-javascript">DELETE /users/101
</code></pre>
<p>This may delete the user having ID <code>101</code>.</p>
<p>Express example:</p>
<pre><code class="language-javascript">app.delete("/users/:id", (req, res) =&gt; {
  res.send("User deleted");
});
</code></pre>
<p>This keeps route structures clean because the route remains the same while the HTTP method changes the operation.</p>
<h3>Designing Routes Using REST Principles</h3>
<p>One major beginner mistake is creating routes like:</p>
<pre><code class="language-javascript">/createUser
/deleteUser
/updateUser
</code></pre>
<p>While these technically work, REST APIs usually avoid action-based route naming.<br />Instead, REST focuses on resource-based routes:</p>
<pre><code class="language-javascript">/users
/users/:id
</code></pre>
<p>The HTTP method itself defines the action.<br />For example:</p>
<pre><code class="language-javascript">GET /users
POST /users
PUT /users/101
DELETE /users/101
</code></pre>
<p>This structure keeps APIs predictable and much easier to scale later.</p>
<h3>Understanding Status Codes</h3>
<p>Whenever the server responds to a request, it also sends a status code. Status codes help the client understand whether the request succeeded or failed.<br />Some very common status codes are:</p>
<ul>
<li><p><code>200</code> → Success</p>
</li>
<li><p><code>201</code> → Resource created</p>
</li>
<li><p><code>400</code> → Bad request</p>
</li>
<li><p><code>404</code> → Resource not found</p>
</li>
<li><p><code>500</code> → Internal server error</p>
</li>
</ul>
<p>Express example:</p>
<pre><code class="language-javascript">app.get("/users", (req, res) =&gt; {
  res.status(200).send("Users fetched");
});
</code></pre>
<p>For resource creation:</p>
<pre><code class="language-javascript">app.post("/users", (req, res) =&gt; {
  res.status(201).send("User created");
});
</code></pre>
<p>Status codes make backend communication more meaningful because the frontend immediately understands what happened with the request.</p>
<h3>Example REST API Structure for Users</h3>
<p>A simple REST structure for a users resource may look like this:</p>
<pre><code class="language-javascript">GET /users
GET /users/:id
POST /users
PUT /users/:id
DELETE /users/:id
</code></pre>
<p>This single structure already covers fetching, creating, updating, and deleting users cleanly using REST conventions.</p>
<h3>Why REST APIs Became So Popular</h3>
<p>REST APIs became extremely popular because they are simple, predictable, scalable, and easy to understand. Frontend applications, mobile apps, and third-party services can all communicate with backend systems using the same standardized HTTP approach.<br />REST also keeps route structures clean because developers do not need to invent random naming patterns for every operation. Once someone understands REST conventions, most APIs start feeling naturally readable.</p>
<h1>Final Thoughts</h1>
<p>REST API design may initially look slightly confusing because terms like resources, routes, methods, and status codes appear together. But at its core, REST is mainly about organizing backend communication in a structured and predictable way.</p>
<p>Instead of building action-based routes, REST focuses on resources and HTTP methods. GET fetches data, POST creates data, PUT updates data, and DELETE removes data. Combined with proper status codes and cleaner route structures, REST APIs become much easier to build, maintain, and scale in real-world backend applications using Express.js.</p>
]]></content:encoded></item><item><title><![CDATA[URL Parameters vs Query Strings in Express.js]]></title><description><![CDATA[If you’ve started working with Express.js recently, chances are you’ve already seen URLs containing things like IDs, search filters, page numbers, categories, or query values. Initially, all of these ]]></description><link>https://blogs.gaurangpods.com/url-parameters-vs-query-strings</link><guid isPermaLink="true">https://blogs.gaurangpods.com/url-parameters-vs-query-strings</guid><category><![CDATA[Node.js]]></category><category><![CDATA[backend]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Gaurang Nagar]]></dc:creator><pubDate>Sat, 09 May 2026 19:20:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950f282d7c55cc3d6748277/84ec40d3-e8b6-4f58-934f-b9b3cd72ff7c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you’ve started working with Express.js recently, chances are you’ve already seen URLs containing things like IDs, search filters, page numbers, categories, or query values. Initially, all of these URLs may look similar because they are simply part of the request URL. But while building APIs, understanding the difference between URL parameters and query strings becomes extremely important because both are used for different purposes.<br />A lot of beginners confuse these two concepts because both involve passing data through the URL itself. But once the purpose behind each one becomes clear, deciding when to use params and when to use query strings becomes very straightforward. In this blog, we’ll understand what URL parameters are, what query strings are, how both differ from each other, how to access them in Express.js, and when each one should actually be used in real backend applications.</p>
<h3>What URL Parameters Actually Are</h3>
<p>URL parameters are dynamic values present directly inside the route path. They are mainly used to identify a specific resource. For example:</p>
<pre><code class="language-javascript">/users/101
</code></pre>
<p>Here, <code>101</code> is usually representing a specific user ID.</p>
<p>Similarly:</p>
<pre><code class="language-javascript">/products/55
</code></pre>
<p>Here, <code>55</code> may represent a specific product. In Express.js, URL parameters are defined using a colon (<code>:</code>). Example:</p>
<pre><code class="language-javascript">app.get("/users/:id", (req, res) =&gt; {
  res.send("User Route");
});
</code></pre>
<p>Here, <code>:id</code> becomes a route parameter.</p>
<h3>Accessing URL Parameters in Express.js</h3>
<p>Express provides all route parameters inside <code>req.params</code>. Example:</p>
<pre><code class="language-javascript">app.get("/users/:id", (req, res) =&gt; {
  console.log(req.params);

  res.send("User fetched");
});
</code></pre>
<p>If the request URL is:</p>
<pre><code class="language-javascript">/users/101
</code></pre>
<p>Output:</p>
<pre><code class="language-javascript">{ id: '101' }
</code></pre>
<p>You can directly access the value like this:</p>
<pre><code class="language-javascript">req.params.id
</code></pre>
<p>This is one of the most common patterns used in APIs while fetching specific users, products, posts, orders, or resources from databases. Whenever the value is directly identifying one particular resource, route parameters are usually the better choice because the route itself depends on that value for fetching the correct data.</p>
<h3>What Query Parameters Are</h3>
<p>Query parameters are different. Instead of being part of the route path itself, query strings appear after a question mark (<code>?</code>) in the URL. They are mainly used for filtering, sorting, searching, pagination, or modifying results. Example:</p>
<pre><code class="language-javascript">/products?category=mobile
</code></pre>
<p>Here, <code>category=mobile</code> is a query parameter.</p>
<p>Another example:</p>
<pre><code class="language-javascript">/products?category=mobile&amp;price=low
</code></pre>
<p>Here, multiple query parameters are being passed together. Unlike route parameters, query strings usually do not identify a single specific resource. Instead, they modify how the data should be returned from the server.</p>
<h3>Accessing Query Strings in Express.js</h3>
<p>Express provides query parameters inside <code>req.query</code>. Example:</p>
<pre><code class="language-javascript">app.get("/products", (req, res) =&gt; {
  console.log(req.query);

  res.send("Products fetched");
});
</code></pre>
<p>If the request URL is:</p>
<pre><code class="language-javascript">/products?category=mobile&amp;price=low
</code></pre>
<p>Output:</p>
<pre><code class="language-javascript">{
  category: 'mobile',
  price: 'low'
}
</code></pre>
<p>You can directly access values like this:</p>
<pre><code class="language-javascript">req.query.category
req.query.price
</code></pre>
<p>This is commonly used in APIs for search filters, sorting options, page numbers, and result customization. Most modern APIs heavily use query parameters whenever users need filtered or customized responses from the server.</p>
<h3>Understanding the Core Difference</h3>
<p>This is the main thing beginners should properly understand. URL parameters are generally used when the value is required to identify a specific resource. For example:</p>
<pre><code class="language-javascript">/users/101
</code></pre>
<p>Here, the route itself depends on the user ID because the server needs to know exactly which user is being requested.</p>
<p>On the other hand, query strings are generally optional modifiers or filters. For example:</p>
<pre><code class="language-javascript">/products?category=mobile
</code></pre>
<p>Here, the route still remains <code>/products</code>. The query parameter is simply modifying or filtering the response. That is the biggest conceptual difference between params and query strings in Express.js applications.</p>
<h3>Practical Examples</h3>
<p>Suppose you are building a social media backend. Fetching a specific user profile:</p>
<pre><code class="language-javascript">/users/101
</code></pre>
<p>This should usually use route parameters because the ID identifies one particular user.</p>
<p>Now suppose you are searching posts:</p>
<pre><code class="language-javascript">/posts?tag=nodejs
</code></pre>
<p>This should usually use query parameters because the tag is filtering results, not identifying one exact resource. Similarly, pagination, sorting, filtering, and searching are usually handled through query strings because they modify the returned data rather than uniquely identifying something.</p>
<h3>Combining Params and Query Strings Together</h3>
<p>Both can also be used together in real applications. Example:</p>
<pre><code class="language-javascript">/users/101/posts?page=2
</code></pre>
<p>Here:</p>
<ul>
<li><p><code>101</code> is a route parameter</p>
</li>
<li><p><code>page=2</code> is a query parameter</p>
</li>
</ul>
<p>In Express:</p>
<pre><code class="language-javascript">app.get("/users/:id/posts", (req, res) =&gt; {
  console.log(req.params.id);
  console.log(req.query.page);

  res.send("Posts fetched");
});
</code></pre>
<p>Possible output:</p>
<pre><code class="language-javascript">101
2
</code></pre>
<p>This type of structure is very common in real-world REST APIs because it allows APIs to identify resources while also customizing or paginating the response at the same time.</p>
<h3>When Should You Use Params vs Query?</h3>
<p>A very simple way to decide is this. Use route parameters when the value is necessary to identify a specific resource. Use query parameters when the value modifies, filters, searches, sorts, or customizes the response.</p>
<p>For example:</p>
<pre><code class="language-javascript">/products/55
</code></pre>
<p>Specific product identification.</p>
<p>Whereas:</p>
<pre><code class="language-javascript">/products?sort=price
</code></pre>
<p>Sorting or filtering products. Once this distinction becomes clear, designing cleaner APIs becomes much easier because the URL structure starts naturally making more sense.</p>
<h3>Common Beginner Mistake</h3>
<p>One very common beginner mistake is trying to use query parameters for everything. For example:</p>
<pre><code class="language-javascript">/users?id=101
</code></pre>
<p>While this technically works, most REST API conventions prefer:</p>
<pre><code class="language-javascript">/users/101
</code></pre>
<p>because the user ID directly identifies a specific resource. Using proper URL structure improves API readability and makes routes easier to understand, maintain, and scale later in larger applications.</p>
<h3>Final Thoughts</h3>
<p>URL parameters and query strings may initially look very similar because both pass data through the URL, but their purposes are actually quite different. Route parameters are mainly used for identifying resources, whereas query parameters are used for filtering, searching, sorting, pagination, or modifying responses.</p>
<p>Once this distinction becomes clear, designing clean REST APIs in Express.js becomes much easier because you’ll naturally know which type of data belongs in the route path and which belongs inside query strings.</p>
]]></content:encoded></item><item><title><![CDATA[JWT Authentication in Node.js Explained Simply]]></title><description><![CDATA[If you have started backend development recently, chances are you’ve heard terms like authentication, tokens, JWT, protected routes, and authorization being used everywhere. Initially, all of this can]]></description><link>https://blogs.gaurangpods.com/jwt-authentication-in-nodejs</link><guid isPermaLink="true">https://blogs.gaurangpods.com/jwt-authentication-in-nodejs</guid><category><![CDATA[JWT]]></category><category><![CDATA[authentication]]></category><category><![CDATA[authorization]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[backend]]></category><dc:creator><![CDATA[Gaurang Nagar]]></dc:creator><pubDate>Sat, 09 May 2026 05:16:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950f282d7c55cc3d6748277/d3405fbe-9d0c-4eee-a227-06068c3d0723.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you have started backend development recently, chances are you’ve heard terms like authentication, tokens, JWT, protected routes, and authorization being used everywhere. Initially, all of this can feel slightly confusing because authentication systems involve many moving parts together. But honestly, once the core idea behind JWT becomes clear, the entire flow starts making much more sense.<br />Authentication is one of the most important parts of backend development because applications need a way to identify users securely. Whether it’s social media platforms, banking apps, e-commerce websites, or streaming services, almost every application needs some form of authentication system so users can log in and access their own data securely.</p>
<p>In this blog, we’ll understand what authentication actually means, what JWT is, how JWT-based login works, the structure of a JWT token, how tokens are sent with requests, and how protected routes work in Node.js applications.</p>
<h3>What Authentication Actually Means</h3>
<p>Authentication simply means verifying whether a user is genuinely who they claim to be.</p>
<p>For example, when you enter your email and password on a website, the backend checks whether those credentials are correct or not. If they are correct, the server identifies you as a valid user and allows access to protected resources.<br />Without authentication, applications would have no proper way to differentiate between users. Anyone could access anyone’s private information, which would obviously become a huge security problem.</p>
<h3>Why Authentication is Required</h3>
<p>Imagine platforms like Instagram, Netflix, or Gmail without authentication. Every user’s private data would become publicly accessible. Authentication exists to prevent that situation.<br />Applications need a way to:</p>
<ul>
<li><p>Identify users</p>
</li>
<li><p>Verify login credentials</p>
</li>
<li><p>Protect private routes</p>
</li>
<li><p>Restrict unauthorized access</p>
</li>
</ul>
<p>This is where token-based authentication systems like JWT became extremely popular.</p>
<h3>What Exactly is JWT?</h3>
<p>JWT stands for JSON Web Token.<br />It is a token-based authentication mechanism where the server generates a token after successful login and sends that token to the client. The client then sends the same token with future requests to prove identity.<br />Instead of storing login sessions on the server side continuously, JWT allows applications to verify users using tokens themselves. This is why JWT authentication is often called stateless authentication because the server does not need to store active login sessions separately for every user.</p>
<h3>Understanding Stateless Authentication</h3>
<p>In traditional session-based authentication, the server stores user session information internally. Every time the client makes a request, the server checks its stored session data to identify the user.<br />JWT works differently.<br />Here, the token itself contains the required user-related information. The client stores the token and sends it along with requests. The server verifies the token and identifies the user from it.<br />This makes JWT authentication lightweight and scalable for modern APIs and frontend-backend architectures.</p>
<h3>Structure of a JWT</h3>
<p>A JWT mainly contains three parts:</p>
<ul>
<li><p>Header</p>
</li>
<li><p>Payload</p>
</li>
<li><p>Signature</p>
</li>
</ul>
<p>These three parts are separated using dots.<br />A JWT looks something like this:</p>
<pre><code class="language-javascript">xxxxx.yyyyy.zzzzz
</code></pre>
<p>Each part has its own purpose.</p>
<h3>Header</h3>
<p>The header contains information about the token type and signing algorithm being used.<br />A very simplified example:</p>
<pre><code class="language-javascript">{
  "alg": "HS256",
  "typ": "JWT"
}
</code></pre>
<p>This tells the server what algorithm was used while generating the token.</p>
<h3>Payload</h3>
<p>The payload contains actual user-related information.<br />For example:</p>
<pre><code class="language-javascript">{
  "id": "123",
  "email": "user@gmail.com"
}
</code></pre>
<p>This data is often called claims. Usually, applications store user IDs, emails, or roles inside the payload.</p>
<h3>Signature</h3>
<p>The signature is responsible for verifying whether the token was modified or not. It is generated using a secret key on the server side.<br />You do not need to go deep into cryptography initially. The important thing to understand is that the signature helps maintain token integrity and prevents tampering.</p>
<h3>Login Flow Using JWT</h3>
<p>Now let’s understand the complete login flow at a high level.<br />When the user logs in:</p>
<ul>
<li><p>Client sends email and password</p>
</li>
<li><p>Server verifies credentials</p>
</li>
<li><p>If credentials are correct, server generates JWT</p>
</li>
<li><p>Token gets sent back to the client</p>
</li>
<li><p>Client stores the token</p>
</li>
<li><p>Client sends the token with future requests</p>
</li>
</ul>
<p>This token becomes the user’s identity proof for protected API access.</p>
<h3>Generating JWT in Node.js</h3>
<p>To generate JWT in Node.js, applications commonly use the jsonwebtoken package.<br />Example:</p>
<pre><code class="language-javascript">const jwt = require("jsonwebtoken");

const token = jwt.sign(
  { id: 1, email: "user@gmail.com" },
  "secretkey",
  { expiresIn: "1h" }
);

console.log(token);
</code></pre>
<p>Here:</p>
<ul>
<li><p>jwt.sign() creates the token</p>
</li>
<li><p>Payload contains user data</p>
</li>
<li><p>"secretkey" is used for signature generation</p>
</li>
<li><p>expiresIn defines token expiry time</p>
</li>
</ul>
<p>After generation, this token is usually sent back to the frontend.</p>
<h3>Sending Token with Requests</h3>
<p>Once the client receives the token, it sends the token with future API requests.<br />Usually, the token is sent inside request headers.<br />Example:</p>
<pre><code class="language-javascript">Authorization: Bearer your_jwt_token
</code></pre>
<p>Whenever the backend receives a protected request, it checks whether the token is valid or not before allowing access.</p>
<h3>Protecting Routes Using JWT</h3>
<p>Now let’s see a very simple protected route example.</p>
<pre><code class="language-javascript">const jwt = require("jsonwebtoken");

function verifyToken(req, res, next) {
  const token = req.headers.authorization;

  if (!token) {
    return res.send("Access denied");
  }

  try {
    const verified = jwt.verify(token, "secretkey");
    req.user = verified;
    next();
  } catch {
    res.send("Invalid token");
  }
}
</code></pre>
<p>Here:</p>
<ul>
<li><p>jwt.verify() checks token validity</p>
</li>
<li><p>If token is valid, request continues</p>
</li>
<li><p>If token is invalid, access gets denied</p>
</li>
</ul>
<p>This is how protected routes work in JWT authentication systems.</p>
<h3>Why JWT Became So Popular</h3>
<p>JWT became extremely popular because modern applications often have separate frontend and backend systems. Mobile apps, React frontends, APIs, and microservices all needed a lightweight authentication mechanism that worked well across different platforms.<br />Since JWT is stateless, scalable, and easy to send with requests, it became a common choice for API-based authentication systems.</p>
<h3>Final Thoughts</h3>
<p>JWT authentication may initially look slightly complicated because terms like tokens, payloads, headers, signatures, and protected routes appear together. But at its core, the flow is actually very straightforward.<br />The server verifies user credentials, generates a token, sends it to the client, and later verifies that same token whenever protected resources are accessed.<br />That is the core idea behind JWT authentication.<br />Once this flow becomes clear, understanding authentication systems in Node.js becomes much easier because almost every modern backend application eventually uses some form of token-based authentication internally.</p>
<p>Hope it helps!.</p>
]]></content:encoded></item><item><title><![CDATA[Why Node.js is Perfect for Building Fast Web Applications
]]></title><description><![CDATA[If you’ve spent even a little time around backend development, chances are you’ve heard people saying things like “Node.js is extremely fast” or “Node.js is great for scalable applications”. Initially]]></description><link>https://blogs.gaurangpods.com/nodejs-for-fast-web-apps</link><guid isPermaLink="true">https://blogs.gaurangpods.com/nodejs-for-fast-web-apps</guid><category><![CDATA[Node.js]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[backend]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Gaurang Nagar]]></dc:creator><pubDate>Sat, 09 May 2026 04:31:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950f282d7c55cc3d6748277/a96f7e21-59ad-44de-9b11-a9e87c284a99.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you’ve spent even a little time around backend development, chances are you’ve heard people saying things like “Node.js is extremely fast” or “Node.js is great for scalable applications”. Initially, this can sound slightly confusing because JavaScript itself is single-threaded, and normally people associate speed with multiple threads and heavy processing power. So naturally the question becomes, what exactly makes Node.js so fast and why do so many companies use it for modern web applications?<br />The answer mainly lies in how Node.js handles requests and manages waiting operations. Instead of blocking the server while one operation completes, Node.js keeps handling other incoming requests efficiently. This behavior made Node.js extremely popular for APIs, real-time systems, streaming platforms, and applications where lots of users interact together continuously.<br />In this blog, we’ll understand what makes Node.js fast, how non-blocking I/O works, why the event-driven architecture matters, how the single-threaded model actually helps, and where Node.js performs best in real-world applications.</p>
<h3>What Actually Makes Node.js Fast?</h3>
<p>One important thing to understand is that Node.js is not fast because JavaScript itself suddenly became magically powerful. The real reason behind Node.js performance is its execution model.<br />Traditional backend systems often spend a lot of time waiting. For example, while reading files, querying databases, or calling APIs, the server may sit idle waiting for responses. If multiple users arrive together, these waiting operations can slow the entire system down.Node.js works differently.<br />Instead of waiting for one operation to finish before handling the next request, Node.js performs slow tasks asynchronously and continues processing other incoming requests. This allows the server to remain responsive even under heavy traffic.</p>
<h3>Understanding Non-Blocking I/O</h3>
<p>One of the biggest reasons behind Node.js speed is non-blocking I/O.</p>
<p>I/O simply refers to input and output operations like:</p>
<ul>
<li><p>File handling</p>
</li>
<li><p>Database communication</p>
</li>
<li><p>API requests</p>
</li>
<li><p>Network operations</p>
</li>
</ul>
<p>In blocking systems, the server waits for these operations to finish completely before moving ahead. In non-blocking systems like Node.js, the operation starts in the background while the server continues handling other tasks. For example:</p>
<pre><code class="language-javascript">const fs = require("fs");

console.log("Reading started");

fs.readFile("sample.txt", "utf-8", (err, data) =&gt; {
  console.log(data);
});

console.log("Other requests continue");
</code></pre>
<p>Possible output:</p>
<pre><code class="language-javascript">Reading started
Other requests continue
File content here
</code></pre>
<p>Notice what happened here. Node.js did not stop execution while reading the file. Instead, it started the operation in the background and continued executing the remaining code immediately. Once the file reading completed, the callback executed later.<br />This is exactly what makes Node.js highly efficient for applications handling many simultaneous users.</p>
<h3>Event-Driven Architecture in Node.js</h3>
<p>Another major reason behind Node.js performance is its event-driven architecture.<br />Node.js works around events and callbacks. Whenever an operation completes, an event gets triggered and the corresponding callback executes. Instead of continuously waiting for operations, Node.js reacts whenever something becomes ready. For example:</p>
<pre><code class="language-javascript">const EventEmitter = require("events");

const emitter = new EventEmitter();

emitter.on("message", () =&gt; {
  console.log("Event received");
});

emitter.emit("message");
</code></pre>
<p>Output:</p>
<pre><code class="language-javascript">Event received
</code></pre>
<p>This event-driven flow helps Node.js efficiently manage many activities together without blocking the execution flow unnecessarily.</p>
<h3>Understanding the Single-Threaded Model</h3>
<p>One thing that surprises many beginners is that Node.js mainly uses a single thread for JavaScript execution.<br />Initially, this sounds like a weakness because people often assume multiple threads automatically mean better performance. But Node.js uses its single-threaded model very smartly.<br />Instead of creating many heavy threads for every incoming request, Node.js handles requests asynchronously. Slow operations get delegated to background system workers while the main JavaScript thread continues processing other requests.<br />This reduces thread management overhead and helps Node.js stay lightweight.</p>
<h3>Concurrency vs Parallelism</h3>
<p>A lot of people confuse concurrency with parallelism.<br />Parallelism means multiple tasks are literally executing at the same exact time using multiple CPU cores or threads. Concurrency means multiple tasks are progressing efficiently together without necessarily executing simultaneously.</p>
<p>Node.js mainly focuses on concurrency.</p>
<p>While one operation waits for a database response or file read, Node.js continues handling other incoming requests instead of sitting idle. This creates excellent responsiveness for I/O-heavy applications.</p>
<h3>Blocking vs Non-Blocking Request Handling</h3>
<p>Let’s understand the difference practically.</p>
<p>In blocking systems, suppose one request takes 5 seconds to fetch data from a database. During that time, the server may remain occupied waiting for that operation to finish before efficiently handling other requests.<br />In Node.js, that database operation starts asynchronously in the background while the server continues handling other incoming users immediately.<br />This difference becomes extremely important when thousands of users interact with the application together. Node.js avoids unnecessary waiting and keeps resource utilization efficient.</p>
<h3>Where Node.js Performs Best</h3>
<p>Node.js performs especially well in applications involving continuous I/O operations and real-time communication.</p>
<p>Some common examples include:</p>
<ul>
<li><p>REST APIs</p>
</li>
<li><p>Chat applications</p>
</li>
<li><p>Streaming platforms</p>
</li>
<li><p>Notification systems</p>
</li>
<li><p>Real-time dashboards</p>
</li>
<li><p>Collaborative tools</p>
</li>
<li><p>Gaming backends</p>
</li>
</ul>
<p>These systems constantly communicate with databases, APIs, sockets, or files, and Node.js handles such asynchronous workloads very efficiently.</p>
<h3>Real-World Companies Using Node.js</h3>
<p>Many large companies adopted Node.js because of its scalability and fast request-handling capabilities.<br />Some popular companies using Node.js include:</p>
<ul>
<li><p>Netflix</p>
</li>
<li><p>PayPal</p>
</li>
<li><p>LinkedIn</p>
</li>
<li><p>Uber</p>
</li>
<li><p>Walmart</p>
</li>
</ul>
<p>These companies needed systems capable of handling massive concurrent traffic efficiently, and Node.js became a strong choice for many of those use cases.</p>
<h3>Why Developers Loved Node.js</h3>
<p>Another major reason developers loved Node.js was the ability to use JavaScript across the full stack. Earlier, frontend and backend development often required different languages. With Node.js, developers could use JavaScript both inside the browser and on the server side.<br />This improved development speed, reduced context switching, and simplified full-stack development workflows significantly.</p>
<h3>Final Thoughts</h3>
<p>Node.js became extremely popular because it solved a very important problem efficiently: handling large numbers of concurrent requests without wasting resources waiting unnecessarily.</p>
<p>Its non-blocking I/O model, event-driven architecture, lightweight execution flow, and asynchronous handling system made it perfect for fast modern web applications. Instead of relying heavily on multiple threads, Node.js focused on efficient concurrency and smart request handling.</p>
<p>That is exactly why Node.js performs exceptionally well for APIs, real-time systems, streaming platforms, and applications where responsiveness and scalability matter heavily.</p>
]]></content:encoded></item><item><title><![CDATA[What is Node.js? JavaScript on the Server Explained]]></title><description><![CDATA[If you have recently started backend development, chances are you’ve heard people saying things like “Node.js lets JavaScript run on the server” or “Node.js changed backend development completely”. In]]></description><link>https://blogs.gaurangpods.com/nodejs-server-side</link><guid isPermaLink="true">https://blogs.gaurangpods.com/nodejs-server-side</guid><category><![CDATA[Node.js]]></category><category><![CDATA[basics]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[js]]></category><category><![CDATA[backend]]></category><dc:creator><![CDATA[Gaurang Nagar]]></dc:creator><pubDate>Sat, 09 May 2026 04:11:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950f282d7c55cc3d6748277/95a89f3c-91cb-45bf-8032-96ebbb744233.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you have recently started backend development, chances are you’ve heard people saying things like “Node.js lets JavaScript run on the server” or “Node.js changed backend development completely”. Initially, this can feel slightly confusing because most of us first learned JavaScript inside the browser for things like buttons, forms, animations, or DOM manipulation. So naturally the question becomes, if JavaScript was originally meant for browsers, then how exactly is it now being used for backend servers, APIs, databases, and large-scale applications?<br />This is exactly where Node.js comes into the picture.</p>
<p>Node.js completely changed how developers looked at JavaScript because now the same language could be used both on the frontend and backend. Before Node.js existed, JavaScript was mostly restricted to browsers. But after Node.js arrived, developers could suddenly build full backend applications using JavaScript itself.</p>
<h3>What Exactly is Node.js?</h3>
<p>Node.js is a JavaScript runtime environment that allows JavaScript code to run outside the browser.<br />A lot of beginners initially confuse JavaScript and Node.js as the same thing, but both are different. JavaScript is the programming language itself, whereas Node.js is an environment that executes JavaScript on the server side.<br />For example:</p>
<pre><code class="language-javascript">console.log("Hello from Node.js");
</code></pre>
<p>This code can directly run using Node.js in the terminal without needing any browser. That is the biggest difference Node.js introduced.</p>
<h3>Why JavaScript Was Originally Browser-Only</h3>
<p>When JavaScript was first created, its purpose was to make websites interactive inside browsers. Browsers provided features like the DOM, buttons, forms, and events, and JavaScript worked around those browser features.</p>
<p>For example:</p>
<pre><code class="language-javascript">document.getElementById("btn").addEventListener("click", () =&gt; {
  console.log("Button clicked");
});
</code></pre>
<p>This code depends on browser APIs. Outside browsers, JavaScript initially had no proper environment to execute in. That meant JavaScript could not directly create servers, handle databases, or process backend logic.</p>
<h3>How Node.js Changed Everything</h3>
<p>Node.js solved this problem by providing a runtime environment for JavaScript outside the browser. Instead of browser-related features, Node.js provides backend capabilities like file handling, networking, HTTP servers, and process management.<br />For example:</p>
<pre><code class="language-javascript">const http = require("http");

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

server.listen(3000);
</code></pre>
<p>This small code creates a backend server using JavaScript itself. Before Node.js, JavaScript was never really used for this type of server-side work.</p>
<h3>Understanding the V8 Engine</h3>
<p>One important thing behind Node.js is the V8 engine.</p>
<p>V8 is Google Chrome’s JavaScript engine responsible for compiling and executing JavaScript code efficiently. Node.js internally uses this same engine to run JavaScript outside the browser.<br />So whenever you run a JavaScript file using Node.js, the V8 engine executes that code on your machine.</p>
<h3>JavaScript Runtime vs Programming Language</h3>
<p>This is another important concept beginners often confuse.<br />JavaScript itself is only the language. Things like variables, loops, functions, arrays, and objects belong to JavaScript.But features like file handling, HTTP servers, and timers come from the runtime environment.<br />In browsers, the runtime is the browser itself. On the backend side, the runtime becomes Node.js.</p>
<h3>Event-Driven Architecture in Node.js</h3>
<p>One major reason developers adopted Node.js heavily was its event-driven and non-blocking architecture.<br />Traditional backend systems often blocked execution while waiting for slow operations like database responses or file reads. Node.js handles things differently. It performs slow operations asynchronously and continues handling other tasks instead of waiting unnecessarily.<br />For example:</p>
<pre><code class="language-javascript">const fs = require("fs");

console.log("Reading started");

fs.readFile("sample.txt", "utf-8", (err, data) =&gt; {
  console.log(data);
});

console.log("Other work continues");
</code></pre>
<p>Possible output:</p>
<pre><code class="language-javascript">Reading started
Other work continues
File content here
</code></pre>
<p>Here, Node.js does not stop execution while reading the file. This non-blocking behavior became one of the biggest reasons behind Node.js adoption.</p>
<h3>Node.js vs Traditional Backend Technologies</h3>
<p>Before Node.js became popular, backend development was heavily dominated by technologies like PHP and Java. Many traditional systems created separate threads for handling different client requests.<br />Node.js became popular because it handled concurrency differently using asynchronous execution and an event-driven architecture. Instead of creating many heavy threads, Node.js efficiently handled multiple requests while staying lightweight.<br />This made Node.js especially useful for APIs, chat applications, streaming services, and real-time systems.</p>
<h3>Real-World Use Cases of Node.js</h3>
<p>Today Node.js is used almost everywhere in backend development. It is commonly used for REST APIs, real-time chat applications, streaming platforms, authentication systems, collaborative tools, and notification services.<br />One of the biggest reasons developers loved Node.js was that the same language could now be used for both frontend and backend development. Earlier, developers often had to learn JavaScript for frontend and another language for backend work. Node.js simplified that workflow significantly.</p>
<h3>Final Thoughts</h3>
<p>Node.js was a major turning point in web development because it allowed JavaScript to move beyond browsers and become a serious backend technology. Instead of being limited to frontend interactions, JavaScript could now create servers, handle APIs, process databases, and build scalable backend applications.</p>
<p>At its core, Node.js is simply a runtime environment that executes JavaScript outside the browser using the V8 engine. But its real impact came from its asynchronous event-driven architecture and the ability to use one language across the entire application stack.</p>
]]></content:encoded></item><item><title><![CDATA[Setting Up Your First Node.js Application Step-by-Step]]></title><description><![CDATA[If you are starting your backend journey with Node.js, then one of the very first things you’ll need to do is properly set up Node.js on your system and run your first application. Initially, this pro]]></description><link>https://blogs.gaurangpods.com/setting-nodejs-application</link><guid isPermaLink="true">https://blogs.gaurangpods.com/setting-nodejs-application</guid><category><![CDATA[Node.js]]></category><category><![CDATA[node]]></category><category><![CDATA[backend]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Gaurang Nagar]]></dc:creator><pubDate>Fri, 08 May 2026 19:59:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950f282d7c55cc3d6748277/6c3656b8-ded1-4edd-b7a2-224d5f300f25.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you are starting your backend journey with Node.js, then one of the very first things you’ll need to do is properly set up Node.js on your system and run your first application. Initially, this process may look slightly confusing because terms like runtime, terminal, REPL, and server start appearing together. But honestly, once you go through the setup once, things become very straightforward.<br />In this blog, we’ll install Node.js, verify the installation from the terminal, understand what the Node REPL actually is, create our very first JavaScript file, execute it using Node.js, and finally build a simple Hello World server. The idea here is not to jump into frameworks or advanced backend concepts immediately, but to properly understand the absolute basics first because this setup becomes the foundation for almost everything you’ll build later using Node.js.</p>
<h3>What Exactly is Node.js?</h3>
<p>Before installing Node.js, it is important to understand what it actually is. Node.js is a JavaScript runtime environment that allows us to run JavaScript outside the browser. Normally, JavaScript executes inside browsers like Chrome or Firefox, but Node.js allows JavaScript to run directly on your machine.<br />This is what made JavaScript extremely powerful for backend development because now developers could use the same language for both frontend and backend applications. Node.js internally uses Google Chrome’s V8 JavaScript engine for executing JavaScript code very efficiently.</p>
<h3>Installing Node.js</h3>
<p>Installing Node.js is fairly simple. You just need to visit the official Node.js website and download the installer according to your operating system. Once the installer downloads, you can proceed with the default installation steps normally without changing much.<br />While installing, Node.js also installs npm automatically. npm stands for<br />Node Package Manager and it helps us install libraries and packages later while building applications.<br />After the installation completes, the next step is verifying whether Node.js was installed correctly or not.</p>
<h3>Checking Node.js Installation from Terminal</h3>
<p>To verify the installation, open your terminal or command prompt and run:</p>
<pre><code class="language-javascript">node -v
</code></pre>
<p>If Node.js was installed correctly, you’ll see a version number printed on the screen. Something like:</p>
<pre><code class="language-javascript">v22.0.0
</code></pre>
<p>You can also check the npm version using:</p>
<pre><code class="language-javascript">npm -v
</code></pre>
<p>Again, this should print the installed npm version.<br />If both commands work successfully, then your Node.js setup is ready and you can start executing JavaScript using Node.js.</p>
<h3>Understanding the Node REPL</h3>
<p>Before creating our first file, there’s one important thing worth understanding called the REPL.<br />REPL stands for Read, Evaluate, Print, Loop.<br />It is basically an interactive environment where Node.js executes JavaScript code line by line directly from the terminal. This becomes very useful for quickly testing small snippets without creating separate files every time.</p>
<p>To start the Node REPL, simply type:</p>
<pre><code class="language-javascript">node
</code></pre>
<p>After running this command, you’ll enter the Node.js interactive environment.<br />Now you can directly execute JavaScript like this:</p>
<pre><code class="language-javascript">console.log("Hello from REPL");
</code></pre>
<p>Output:</p>
<pre><code class="language-javascript">Hello from REPL
</code></pre>
<p>You can even perform calculations:</p>
<pre><code class="language-javascript">10 + 20
</code></pre>
<p>Output:</p>
<pre><code class="language-javascript">30
</code></pre>
<p>The REPL is mainly useful for testing things quickly while learning or debugging. To exit the REPL, you can type:</p>
<pre><code class="language-javascript">.exit
</code></pre>
<p>or simply press Ctrl + C twice.</p>
<h3>Creating Your First JavaScript File</h3>
<p>Now let’s create our very first Node.js file.<br />Create a folder anywhere on your system and inside that folder create a file named:</p>
<pre><code class="language-javascript">app.js
</code></pre>
<p>Inside this file, write:</p>
<pre><code class="language-javascript">console.log("Hello World from Node.js");
</code></pre>
<p>This is a very basic JavaScript file, but now instead of running it inside a browser, we’ll execute it using Node.js directly from the terminal.</p>
<h3>Running Your First Node.js Script</h3>
<p>Now open the terminal inside the same folder where your file exists and run:</p>
<pre><code class="language-javascript">node app.js
</code></pre>
<p>Output:</p>
<pre><code class="language-javascript">Hello World from Node.js
</code></pre>
<p>This is officially your first Node.js application running successfully.<br />What actually happened here is that Node.js took your JavaScript file, passed it to the V8 engine, executed the code, and displayed the output in the terminal.</p>
<h3>Understanding the Execution Flow</h3>
<h3>Whenever you run:</h3>
<pre><code class="language-javascript">node app.js
</code></pre>
<p>a simple flow happens internally.</p>
<ul>
<li><p>Node.js reads the file</p>
</li>
<li><p>The V8 engine compiles the JavaScript</p>
</li>
<li><p>The code gets executed</p>
</li>
<li><p>Output appears in the terminal</p>
</li>
</ul>
<p>This is the basic execution flow behind every Node.js application, whether it is a tiny script or a massive backend server.</p>
<h3>Writing Your First Hello World Server</h3>
<p>Now let’s create a very small server using Node.js. This is usually the point where people start feeling excited because now JavaScript is actually creating backend servers.<br />Replace the previous code inside app.js with this:</p>
<pre><code class="language-javascript">const http = require("http");

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

server.listen(3000, () =&gt; {
  console.log("Server running on port 3000");
});
</code></pre>
<p>Now run the file again:</p>
<pre><code class="language-javascript">node app.js
</code></pre>
<p>Output:</p>
<pre><code class="language-javascript">Server running on port 3000
</code></pre>
<p>At this point, your Node.js server is actually running.<br />Now 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 Server
</code></pre>
<p>This is your first backend server running successfully using Node.js.</p>
<h3>Understanding What Happened in the Server Code</h3>
<p>The http module used here is a built-in Node.js module that helps create servers. We used createServer() to create a server instance and passed a callback function that executes whenever a client sends a request to the server.<br />Inside that callback, res.end() sends the response back to the client. Then server.listen() starts the server on port 3000 so the application becomes accessible through the browser.<br />Even though the code is small, this is the starting point for almost every backend application built using Node.js.</p>
<h3>Final Thoughts</h3>
<p>Setting up Node.js and running the first application is an important step because this is where backend development with JavaScript actually begins. Initially, terms like runtime, REPL, server, and terminal may feel slightly unfamiliar, but once you execute your first few programs, things start becoming much more comfortable.<br />In this blog, we installed Node.js, verified the installation using terminal commands, understood the REPL environment, created our first JavaScript file, executed it using Node.js, and finally built a small Hello World server. These may look like simple steps, but they form the foundation for everything you’ll build later using Node.js, whether it’s APIs, authentication systems, databases, or full backend applications.</p>
]]></content:encoded></item><item><title><![CDATA[How Node.js Handles Multiple Requests with a Single Thread]]></title><description><![CDATA[One of the most confusing things people hear while learning Node.js is that Node.js is single-threaded, yet it can handle thousands of requests together. Initially, this sounds contradictory because n]]></description><link>https://blogs.gaurangpods.com/nodejs-multiple-request-handling</link><guid isPermaLink="true">https://blogs.gaurangpods.com/nodejs-multiple-request-handling</guid><category><![CDATA[Node.js]]></category><category><![CDATA[node]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[js]]></category><category><![CDATA[backend]]></category><dc:creator><![CDATA[Gaurang Nagar]]></dc:creator><pubDate>Fri, 08 May 2026 18:51:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950f282d7c55cc3d6748277/a2e7f71c-ade2-4f8f-b1ab-0325802d8a2f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>One of the most confusing things people hear while learning Node.js is that Node.js is single-threaded, yet it can handle thousands of requests together. Initially, this sounds contradictory because normally we assume that if something is handling many users at once, then multiple threads must be working simultaneously in the background. So naturally the question becomes, if Node.js uses a single thread for JavaScript execution, then how is it still capable of managing multiple client requests so efficiently?</p>
<p>This is exactly where concepts like the event loop, asynchronous operations, and background workers become important. A lot of beginners initially think Node.js somehow executes everything in parallel inside JavaScript itself, but that is not actually what happens. Node.js handles concurrency very smartly, and understanding this flow is extremely important if you want to properly understand backend development using Node.js.</p>
<p>In this blog, we’ll understand how Node.js manages multiple requests using a single thread, what role the event loop plays, how slow tasks get delegated to background workers, and why Node.js scales so well for I/O-heavy applications.</p>
<h3>Understanding Single-Threaded Nature of Node.js</h3>
<p>When people say Node.js is single-threaded, they are mainly referring to JavaScript execution. JavaScript inside Node.js runs on a single main thread, which means one piece of JavaScript code executes at a time. If one function is currently running, another function has to wait until the current execution completes. For example:</p>
<pre><code class="language-javascript">function task1() {
  console.log("Task 1 started");
}

function task2() {
  console.log("Task 2 started");
}

task1();
task2();
</code></pre>
<p>&amp; Output:</p>
<pre><code class="language-javascript">Task 1 started
Task 2 started
</code></pre>
<p>Everything executes one after another because JavaScript uses a single call stack for execution. Initially, this may sound like a limitation because we usually associate single-threaded systems with slow performance. But Node.js works differently because it avoids blocking behavior for slow operations.<br />This is why understanding only the “single-threaded” part is incomplete. The real power of Node.js comes from how it handles asynchronous operations around that single thread.</p>
<h3>Thread vs Process in Simple Terms</h3>
<p>A process can be thought of as an independent running application. Inside a process, there can be one or multiple threads. Threads are smaller execution units responsible for performing tasks inside the process.<br />Traditional backend systems often create multiple threads to handle multiple users simultaneously. Node.js takes a different approach. Instead of creating separate threads for every incoming request, Node.js mainly relies on a single JavaScript thread combined with asynchronous non-blocking execution.<br />This makes Node.js lightweight because creating too many threads can increase memory usage and context-switching overhead. Node.js tries to avoid that problem by efficiently handling waiting operations in the background instead of keeping multiple threads busy doing nothing.</p>
<h3>So How Does Node.js Handle Multiple Requests?</h3>
<p>This is where the event loop becomes extremely important.</p>
<p>Suppose multiple users send requests to a Node.js server together. The JavaScript thread starts processing those requests one by one, but whenever a slow operation appears, Node.js does not block the thread waiting for that operation to complete.<br />Instead, it delegates the slow task to background system workers and immediately continues handling other incoming requests. For example:</p>
<pre><code class="language-javascript">const fs = require("fs");

console.log("Request 1 started");

fs.readFile("sample.txt", "utf-8", (err, data) =&gt; {
  console.log("File reading completed");
});

console.log("Request 2 started");
</code></pre>
<p>Possible output:</p>
<pre><code class="language-javascript">Request 1 started
Request 2 started
File reading completed
</code></pre>
<p>Notice what happened here. The file reading operation did not block JavaScript execution. Node.js handed over the file operation to the system-level APIs running in the background and immediately continued processing the next request. Once the file operation completed, its callback became ready for execution later.<br />This is one of the biggest reasons Node.js can keep handling many incoming requests efficiently even while using a single JavaScript thread.</p>
<h3>Role of the Event Loop in Concurrency</h3>
<p>The event loop acts like a coordinator between JavaScript execution and completed asynchronous operations. Its job is to continuously check whether the call stack is empty and whether any completed async callbacks are waiting.<br />If the stack becomes free, the event loop pushes ready callbacks into execution.<br />This allows Node.js to keep moving between multiple tasks efficiently without blocking the main thread unnecessarily. The event loop itself does not magically execute multiple JavaScript functions together simultaneously. Instead, it smartly schedules completed operations for execution whenever JavaScript becomes free.</p>
<p>This is an important point because Node.js mainly achieves concurrency, not true parallel JavaScript execution on the main thread.</p>
<h3>Concurrency vs Parallelism</h3>
<p>A lot of people confuse concurrency with parallelism, but both are different things.<br />Parallelism means multiple tasks are literally executing at the exact same moment on multiple CPU cores or threads. Concurrency means multiple tasks are progressing efficiently together without necessarily executing simultaneously.</p>
<p>Node.js mainly focuses on concurrency. It quickly switches between operations and avoids unnecessary waiting. Slow operations continue in the background while JavaScript keeps processing other requests.<br />This creates the feeling that many things are happening together even though the main JavaScript execution itself is still single-threaded.</p>
<h3>Delegating Tasks to Background Workers</h3>
<p>One important thing to understand is that Node.js does not perform slow I/O operations directly using the JavaScript thread. Operations like file reading, database communication, network requests, DNS lookups, and some cryptographic operations are delegated to underlying system APIs and worker threads managed internally by Node.js.</p>
<p>JavaScript itself only registers callbacks and continues execution. For example:</p>
<pre><code class="language-javascript">const crypto = require("crypto");

console.log("Hashing started");

crypto.pbkdf2("password", "salt", 100000, 64, "sha512", () =&gt; {
  console.log("Hash generated");
});

console.log("Handling other requests");
</code></pre>
<p>&amp; possible output:</p>
<pre><code class="language-javascript">Hashing started
Handling other requests
Hash generated
</code></pre>
<p>While the heavy hashing operation was happening in the background, JavaScript continued handling other work. This delegation system is extremely important for maintaining responsiveness under high traffic.</p>
<h3>Why Node.js Scales So Well</h3>
<p>The reason Node.js scales efficiently is because it spends very little time waiting idly. In traditional blocking systems, a thread may sit inactive while waiting for database responses, file reads, or API results. If many users arrive together, a large number of threads may become occupied simply waiting.</p>
<p>Node.js avoids this issue by using asynchronous non-blocking execution. Instead of waiting for one request to finish completely before handling others, Node.js keeps moving ahead with other incoming work while slow operations continue in the background.<br />This leads to better resource utilization and allows Node.js servers to handle a large number of concurrent users efficiently without consuming massive system resources.<br />That is exactly why Node.js became extremely popular for APIs, real-time applications, streaming platforms, chat systems, and notification services where large amounts of I/O operations happen continuously.</p>
<h3>A Small Request Flow Example</h3>
<p>Suppose three users send requests almost together:</p>
<ul>
<li><p>User 1 requests file data</p>
</li>
<li><p>User 2 requests database data</p>
</li>
<li><p>User 3 requests API response</p>
</li>
</ul>
<p>Node.js starts each request, delegates the slow operations to background handlers, and continues accepting more incoming requests instead of waiting for one operation to finish first.<br />As soon as any operation completes, its callback becomes ready, and the event loop schedules it for execution whenever the call stack becomes available.<br />This is how one JavaScript thread efficiently handles many client requests together without becoming blocked.</p>
<h3>Final Thoughts</h3>
<p>Initially, hearing that Node.js is single-threaded can make it sound weak compared to systems using multiple threads. But the real strength of Node.js comes from how efficiently it handles asynchronous non-blocking operations around that single thread.<br />Instead of wasting resources waiting for slow operations to complete, Node.js delegates those operations to background workers and keeps the main thread free for handling other incoming requests. The event loop continuously coordinates completed operations and schedules their execution whenever JavaScript becomes available.</p>
<p>This combination of asynchronous execution, background delegation, and efficient concurrency is what allows Node.js to handle multiple requests so effectively while still using a single JavaScript thread.</p>
]]></content:encoded></item><item><title><![CDATA[Blocking vs Non-Blocking Code in Node.js]]></title><description><![CDATA[If you have started learning Node.js recently, chances are you’ve heard people saying things like “Node.js is non-blocking” or “blocking operations are bad for performance”. Initially, these terms sou]]></description><link>https://blogs.gaurangpods.com/blocking-vs-non-blocking-code-in-node-js</link><guid isPermaLink="true">https://blogs.gaurangpods.com/blocking-vs-non-blocking-code-in-node-js</guid><category><![CDATA[Node.js]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[js]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[backend]]></category><dc:creator><![CDATA[Gaurang Nagar]]></dc:creator><pubDate>Fri, 08 May 2026 17:45:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950f282d7c55cc3d6748277/41b40492-3036-4efb-9f29-cdc8273ec29a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you have started learning Node.js recently, chances are you’ve heard people saying things like “Node.js is non-blocking” or “blocking operations are bad for performance”. Initially, these terms sound a bit confusing because when we write code normally, everything feels like it executes one after another anyway. So naturally the question becomes, what exactly is blocking code, what is non-blocking code, and why does Node.js care so much about this difference?</p>
<p>This concept is actually one of the biggest reasons why Node.js became so popular for backend development. Once you understand blocking vs non-blocking execution properly, a lot of other concepts like async programming, callbacks, promises, APIs, and even the event loop start making much more sense. In this blog, we’ll understand what blocking and non-blocking code actually means, why blocking operations can slow down servers, how Node.js handles async tasks internally at a high level, and why non-blocking behavior helps Node.js applications stay scalable.</p>
<h3>What Blocking Code Actually Means</h3>
<p>Blocking code simply means that one operation blocks the execution of everything that comes after it until it finishes completely. JavaScript executes code line by line, and if one particular operation takes a lot of time, the remaining code has to wait there patiently until that operation gets completed. During this waiting period, nothing else moves ahead because the current task is still occupying the execution flow. A simple example can make this much clearer.</p>
<pre><code class="language-javascript">function slowTask() {
  const start = Date.now();

  while (Date.now() - start &lt; 5000) {
    
  }

  console.log("Slow task completed");
}

function nextTask() {
  console.log("Next task executed");
}

slowTask();
nextTask();
</code></pre>
<p>and output after 5 seconds:</p>
<pre><code class="language-javascript">Slow task completed
Next task executed
</code></pre>
<p>Here, the second function could not execute immediately because the first function blocked the execution for 5 seconds. JavaScript was completely busy with the current task and could not move ahead until it finished. This type of behavior is called blocking execution because one operation blocks everything behind it.</p>
<h3>Why Blocking Code Becomes a Problem on Servers</h3>
<p>In small programs, blocking code may not feel like a huge issue. But on backend servers, this can become a serious performance problem very quickly. Imagine a server receiving requests from multiple users together. If one user triggers a slow operation and the server blocks during that time, then other users also get stuck waiting unnecessarily.</p>
<p>Suppose one user requests a large file from the database and reading that file takes several seconds. If the server uses blocking operations, then during those few seconds the server may not efficiently process other incoming requests. This directly affects responsiveness and scalability because users start experiencing delays even for small operations.</p>
<p>This is one of the biggest reasons why backend systems try to avoid blocking behavior as much as possible. Instead of waiting for slow operations to complete, modern systems prefer continuing with other tasks and handling the result later whenever it becomes available.</p>
<h3>What Non-Blocking Code Means</h3>
<p>Non-blocking code works differently. Instead of waiting for a slow operation to finish completely, Node.js starts that operation in the background and immediately continues executing the remaining code. Once the operation finishes, its callback or result gets handled later. This allows the application to stay responsive instead of getting stuck waiting. For example:</p>
<pre><code class="language-javascript">const fs = require("fs");

console.log("Reading file started");

fs.readFile("sample.txt", "utf-8", (err, data) =&gt; {
  console.log(data);
});

console.log("Other operations continue");
</code></pre>
<p>Possible output:</p>
<pre><code class="language-javascript">Reading file started
Other operations continue
File content here
</code></pre>
<p>Notice something important here. The file reading operation did not block the execution flow. Node.js started reading the file in the background and immediately continued executing the remaining code. Once the file reading completed, the callback function executed later with the file data. This is exactly what non-blocking execution means.</p>
<h3>How Async Operations Help in Non-Blocking Execution</h3>
<p>The reason Node.js achieves non-blocking behavior is because of asynchronous operations. Operations like file handling, database queries, API requests, and timers are generally slow compared to normal JavaScript execution. Instead of making JavaScript wait for them, Node.js delegates these operations to system-level components running in the background.<br />JavaScript itself does not sit idle waiting for the result. It simply registers the callback function and continues moving ahead with the remaining execution flow. Once the operation completes, the callback becomes ready and eventually gets executed. For example:</p>
<pre><code class="language-javascript">console.log("Start");

setTimeout(() =&gt; {
  console.log("Timer completed");
}, 3000);

console.log("End");
</code></pre>
<p>Output:</p>
<pre><code class="language-javascript">Start
End
Timer completed
</code></pre>
<p>Here, the timer operation did not stop JavaScript execution for 3 seconds. Node.js handled the timer separately while JavaScript continued executing the remaining lines immediately. Once the timer duration completed, the callback executed later. This is one of the most basic examples of asynchronous non-blocking behavior in Node.js.</p>
<h3>Blocking vs Non-Blocking File Handling</h3>
<p>File handling is one of the best places to understand the difference between blocking and non-blocking execution because Node.js provides both versions.<br />First, let’s see blocking file reading.</p>
<pre><code class="language-javascript">const fs = require("fs");

console.log("Reading started");

const data = fs.readFileSync("sample.txt", "utf-8");

console.log(data);

console.log("Execution completed");
</code></pre>
<p>In this case, Node.js waits completely until the file is fully read. Only after the file reading operation finishes does the remaining code continue execution. This is blocking behavior because the execution flow remains stuck during the file reading process.<br />Now let’s see the non-blocking version.</p>
<pre><code class="language-javascript">const fs = require("fs");

console.log("Reading started");

fs.readFile("sample.txt", "utf-8", (err, data) =&gt; {
  console.log(data);
});

console.log("Execution completed");
</code></pre>
<p>Here, Node.js immediately moves ahead after starting the file read operation. The server does not sit idle waiting for the file content. Once the reading finishes, the callback executes later with the data. This is non-blocking behavior and it is much more efficient for backend applications handling multiple users together.</p>
<h3>Real World Impact on Server Performance</h3>
<p>The difference between blocking and non-blocking code becomes extremely important when traffic increases. A blocking server may spend a lot of time waiting for slow operations to finish, which means fewer requests get processed efficiently during that period. As more users arrive, delays start increasing and performance begins degrading.<br />Non-blocking systems behave much better in these situations because they do not waste time waiting unnecessarily. While one operation is happening in the background, the server can continue handling other incoming requests. This improves concurrency, responsiveness, and overall scalability.</p>
<p>This is exactly why Node.js became very popular for APIs, chat applications, streaming systems, notification services, and real-time applications where continuous I/O operations happen all the time. Most backend operations involve waiting for something external like databases, APIs, or file systems, and Node.js handles these situations very efficiently using asynchronous non-blocking behavior.</p>
<h3>Does Non-Blocking Mean Everything Runs Simultaneously?</h3>
<p>One common misconception is that non-blocking means JavaScript executes multiple things together simultaneously. That is not exactly true. JavaScript itself still runs on a single thread. What actually happens is that slow operations are delegated outside the main execution flow, and JavaScript continues handling other work while those operations complete in the background.<br />So non-blocking does not mean JavaScript suddenly becomes multi-threaded. It simply means JavaScript does not unnecessarily wait for slow operations before continuing execution.</p>
<h3>Final Thoughts</h3>
<p>Understanding blocking vs non-blocking code is one of the most important steps in learning Node.js properly because this concept directly affects how backend applications perform under load. Blocking operations can slow down servers by forcing the execution flow to wait unnecessarily, whereas non-blocking operations allow the server to stay responsive while slow tasks continue in the background.</p>
<p>This entire approach is deeply connected to asynchronous programming in Node.js. Whether you are working with databases, APIs, file systems, timers, or sockets, you’ll constantly encounter non-blocking behavior everywhere. Once this concept becomes clear, understanding callbacks, promises, async-await, and the event loop becomes much easier because all of them are built around the same core idea of avoiding unnecessary waiting during execution.</p>
<p>Hope it helps!.</p>
]]></content:encoded></item><item><title><![CDATA[Understanding the Event Loop in Node.js]]></title><description><![CDATA[If you have worked with Node.js for even a short time, chances are you’ve heard people saying things like “Node is single-threaded” or “Node works because of the event loop”. Initially, these terms so]]></description><link>https://blogs.gaurangpods.com/event-loop-in-nodejs</link><guid isPermaLink="true">https://blogs.gaurangpods.com/event-loop-in-nodejs</guid><category><![CDATA[Node.js]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Event Loop]]></category><dc:creator><![CDATA[Gaurang Nagar]]></dc:creator><pubDate>Fri, 08 May 2026 04:57:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950f282d7c55cc3d6748277/886899cd-097a-446a-80b7-7c858edc58ed.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you have worked with Node.js for even a short time, chances are you’ve heard people saying things like “Node is single-threaded” or “Node works because of the event loop”. Initially, these terms sound a bit confusing because on one side people say JavaScript runs on a single thread, and on the other side they also say Node.js can handle thousands of users together. So naturally the question becomes, if Node.js is single-threaded, then how is it handling so many things at once?</p>
<p>This is exactly where the event loop comes into the picture.<br />In this blog, we’ll understand what the event loop actually is, why Node.js needs it, how async operations work internally at a high level, and how all of this helps Node.js stay scalable. By the end, the whole “single-threaded but still asynchronous” thing will make much more sense.</p>
<h3>Why Node.js Needed Something Like the Event Loop</h3>
<p>Before understanding the event loop, we first need to understand the problem. JavaScript itself runs on a single thread. That simply means one thing executes at a time. Suppose JavaScript starts executing one function. Until that function finishes, the next function has to wait. This happens because JavaScript uses something called a call stack. Everything that executes in JavaScript first enters this stack, gets processed, and only then the next thing gets the chance to execute.<br />This works completely fine for small and fast operations, but the problem starts appearing when one operation becomes slow and blocks everything else behind it. like a very simple example:</p>
<pre><code class="language-javascript">function task1() {
  console.log("Task 1");
}

function task2() {
  console.log("Task 2");
}

task1();
task2();
</code></pre>
<p>It's output:</p>
<pre><code class="language-javascript">Task 1
Task 2
</code></pre>
<p>Everything looks fine here because both operations are quick. But now imagine one operation takes 5 seconds. During those 5 seconds, JavaScript cannot move ahead because the current task is still occupying the call stack.<br />That means every other operation behind it remains stuck until the current task completely finishes execution. This is where blocking behavior starts becoming a serious issue, especially in backend applications where multiple users may be sending requests together at the same time.</p>
<pre><code class="language-javascript">function slowTask() {
  const start = Date.now();

  while (Date.now() - start &lt; 5000) {
    
  }

  console.log("Slow task completed");
}

function anotherTask() {
  console.log("Another task");
}

slowTask();
anotherTask();
</code></pre>
<p>Output after 5 seconds:</p>
<pre><code class="language-javascript">Slow task completed
Another task
</code></pre>
<p>Notice something important here. The second function had to wait completely. JavaScript could not move ahead until the first task finished. Now imagine this situation on a backend server. Suppose one user requests some large file from the database and the server blocks for a few seconds. If the entire server waits during that time, then every other incoming user also gets stuck. That would be terrible for scalability.</p>
<p>This is why Node.js needed a better mechanism to handle slow operations like database queries, API calls, file handling, timers, and network requests without blocking the entire execution flow.</p>
<h3>So What Exactly is the Event Loop?</h3>
<p>At a very high level, the event loop is simply a manager. Its job is to continuously check whether the call stack is empty and whether there are any completed async tasks waiting for execution. If the stack becomes empty and some async callback is ready, the event loop pushes that callback into the call stack so JavaScript can execute it. That’s the core idea behind the entire flow.<br />Node.js itself does not magically execute everything simultaneously inside JavaScript. Instead, it smartly delegates slow operations outside the main thread and keeps checking when those operations are completed so their callbacks can be executed later without blocking everything else.</p>
<h3>Understanding the Flow Step by Step</h3>
<p>Let’s take a small example first.</p>
<pre><code class="language-javascript">console.log("Start");

setTimeout(() =&gt; {
  console.log("Timer completed");
}, 2000);

console.log("End");
</code></pre>
<p>It's output:</p>
<pre><code class="language-javascript">Start
End
Timer completed
</code></pre>
<p>At first this feels weird because many people expect the timer callback to execute before “End”. But the reason this does not happen is because the timer operation is asynchronous. When the code starts executing, “Start” goes into the call stack and executes immediately. Then setTimeout gets registered and Node.js hands over the timer responsibility to the underlying system APIs.<br />JavaScript does not stop and wait there. It immediately moves ahead and executes “End”. Once the timer duration completes after 2 seconds, the callback becomes ready. The event loop keeps checking whether the call stack is empty, and once it becomes empty, the callback is pushed into the stack and finally executes. This is the reason Node.js feels non-blocking even though JavaScript itself is single-threaded.</p>
<h3>Call Stack vs Task Queue</h3>
<p>To understand the event loop properly, these two concepts are important. The call stack is where functions execute, whereas the task queue stores completed async callbacks that are waiting for execution. Whenever an async operation completes, its callback does not directly jump into execution immediately. Instead, it first waits inside the queue.<br />The event loop continuously checks whether the call stack has become empty or not. If the stack is empty, then the callback is moved from the queue into the stack for execution. This entire cycle keeps repeating continuously while the application runs. At a conceptual level, this is the main relationship between the call stack, task queue, and the event loop.</p>
<h3>Async Operations are Not Executed by JavaScript Alone</h3>
<p>One common misconception is that JavaScript itself handles timers, file system operations, or network requests. It actually doesn’t. Things like setTimeout, file system operations, and HTTP requests are handled by Node.js APIs and system-level components running in the background. JavaScript only registers the callback function and continues moving ahead with the remaining code execution. Once the operation completes in the background, the callback is sent back and the event loop schedules it for execution whenever the call stack becomes free. This is why async operations do not block the main execution flow. For example:</p>
<pre><code class="language-javascript">const fs = require("fs");

console.log("Reading file...");

fs.readFile("sample.txt", "utf-8", (err, data) =&gt; {
  console.log(data);
});

console.log("Other work continues...");
</code></pre>
<p>It's output:</p>
<pre><code class="language-javascript">Reading file...
Other work continues...
File content here
</code></pre>
<p>Notice again that JavaScript did not stop and wait for the file to be read completely. While the file system operation was happening in the background, JavaScript continued executing the remaining code normally. Once the file reading operation completed, its callback was brought back for execution. This is one of the biggest reasons Node.js performs well for backend applications where multiple I/O operations happen continuously.</p>
<h3>Timers vs I/O Callbacks</h3>
<p>At a high level, different async operations get handled differently internally. Timers like setTimeout wait for time completion, whereas I/O callbacks wait for operations like file reading, database queries, or network requests to finish. Internally, Node.js has different mechanisms to manage these operations efficiently, but from a beginner perspective, the important thing to understand is that both eventually place their callbacks into queues and the event loop decides when those callbacks should execute. You do not need to go very deep into internal phases initially because understanding the overall flow is far more important in the beginning.</p>
<h3>Why the Event Loop Makes Node.js Scalable</h3>
<p>This is probably the most important part of the entire discussion. Traditional blocking systems can waste a lot of time waiting for operations like database responses, file reads, or API results. During this waiting period, the server may become blocked and unable to efficiently process other incoming requests. Node.js avoids this issue completely by using asynchronous behavior along with the event loop. Instead of sitting idle and waiting for one operation to finish, Node.js keeps accepting and processing other requests while the slow operations continue in the background.</p>
<p>This leads to much better resource utilization and allows Node.js applications to handle a very large number of concurrent users efficiently. This is exactly why Node.js became extremely popular for APIs, real-time applications, chat systems, streaming platforms, and notification systems where continuous I/O operations are happening all the time. The event loop plays a huge role in making all of this possible because it allows JavaScript to stay non-blocking without creating unnecessary waiting situations.</p>
<h3>Final Thoughts</h3>
<p>The event loop is one of the most important concepts in Node.js because it explains how Node.js achieves asynchronous and non-blocking behavior even while JavaScript itself is single-threaded. Initially, the internals can feel confusing, especially when terms like queues, stacks, callbacks, and async operations start appearing together. But at its core, the idea is actually simple. JavaScript executes one thing at a time, slow operations get delegated outside the main thread, completed callbacks wait in queues, and the event loop keeps moving ready callbacks back into execution whenever the call stack becomes free.</p>
<p>Once this flow becomes clear, understanding async programming in Node.js becomes much easier because almost everything in backend development eventually connects back to this concept in one way or another. Whether you are working with APIs, databases, timers, sockets, or file handling, the event loop is constantly working in the background and making asynchronous execution possible.</p>
<p>I hope it helps.</p>
]]></content:encoded></item><item><title><![CDATA[Sessions vs JWT vs Cookies: Understanding Authentication Approaches]]></title><description><![CDATA[When we start learning backend, authentication feels confusing mainly because terms like sessions, cookies, and JWT are often mixed together in tutorials. Sometimes people even use them interchangeabl]]></description><link>https://blogs.gaurangpods.com/sessions-jwt-cookies</link><guid isPermaLink="true">https://blogs.gaurangpods.com/sessions-jwt-cookies</guid><category><![CDATA[JWT]]></category><category><![CDATA[authentication]]></category><category><![CDATA[backend]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Gaurang Nagar]]></dc:creator><pubDate>Thu, 07 May 2026 23:03:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950f282d7c55cc3d6748277/3ba9499d-ce0f-46e3-8176-bd11089ca851.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When we start learning backend, authentication feels confusing mainly because terms like sessions, cookies, and JWT are often mixed together in tutorials. Sometimes people even use them interchangeably, which makes things even more confusing. I remember initially thinking cookies and sessions were the same thing. Then JWT entered the picture and suddenly everything looked like three different authentication systems competing with each other.<br />But honestly, once you understand what each thing actually does, the whole flow starts making sense. In this blog, we’ll understand what sessions are, what cookies are, what JWT tokens are, how stateful and stateless authentication work, and when you would actually use each approach in real projects.</p>
<h2>What Are Cookies?</h2>
<p>Cookies are small pieces of data stored inside the browser. Whenever a client sends a request to the server, the browser can automatically attach cookies along with that request. A cookie itself is not authentication. It is just a storage mechanism. For example, after login, the server may store something like this in the browser, and from there the browser keeps sending it automatically with future requests.<br />The important thing to understand is that cookies are simply used to store some data on the client side, and that data could be a session ID, a JWT token, user preferences, language settings, theme settings, or anything else.</p>
<pre><code class="language-javascript">document.cookie = "userId=12345";
</code></pre>
<p>Now every request can automatically carry this cookie.</p>
<pre><code class="language-javascript">Cookie: userId=12345
</code></pre>
<p>So cookies are storage. Not authentication logic itself. This is where many beginners get confused because they think cookies and sessions are the same thing, whereas cookies are just one way of storing or transporting some information between client and server.</p>
<h2>What Are Sessions?</h2>
<p>Sessions are a server-side authentication mechanism. When a user logs in successfully, the server creates a session for that user and stores session-related data somewhere on the server. That data may contain details like userId, sessionId, login state, expiry information, etc. Now the server needs some way to identify which session belongs to which user, and for that it usually sends the session ID back to the browser inside a cookie.<br />From the next request onwards, the browser automatically sends that cookie and the server checks whether that session exists and is valid.</p>
<pre><code class="language-javascript">{
  sessionId: "abc123",
  userId: 45,
  isLoggedIn: true
}
</code></pre>
<p>The server may send the session ID like this:</p>
<pre><code class="language-javascript">Set-Cookie: sessionId=abc123
</code></pre>
<p>And from the next request onwards:</p>
<pre><code class="language-javascript">Cookie: sessionId=abc123
</code></pre>
<p>Then the server checks whether this session ID exists, which user it belongs to, and whether the session is still valid or expired. If everything is valid, the request gets authenticated. So in session-based authentication, the session data lives on the server, while the session ID usually lives inside cookies. This is why sessions are called stateful authentication because the server is maintaining state for logged-in users.</p>
<h2>Simple Session Flow</h2>
<p>The flow usually starts when the user logs in and the server creates a session for that user. The server stores the session in memory or a database and then sends a session ID to the browser. The browser stores that session ID inside a cookie and automatically sends it in future requests.<br />Whenever the server receives a request, it checks whether the session ID is valid and maps it back to the stored session data. If the session exists and is active, the user gets authenticated. That is basically the complete idea behind session authentication and once you understand this flow, sessions become very easy to understand.</p>
<h2>What Is JWT?</h2>
<p>JWT stands for JSON Web Token. Unlike sessions, JWT authentication does not require the server to store authentication state separately for every user. Instead, the token itself carries the required information. After login, the server generates a JWT token and sends it to the client. The client then stores that token somewhere, usually inside localStorage, sessionStorage, or sometimes cookies. For every protected request, the token is sent back to the server and the server verifies its signature before authenticating the user.</p>
<p>A JWT payload may look something like this:</p>
<pre><code class="language-javascript">{
  userId: 45,
  role: "admin"
}
</code></pre>
<p>The server may generate it like this:</p>
<pre><code class="language-javascript">const token = generateJWT({
  userId: 45
});
</code></pre>
<p>And future requests may send it like this:</p>
<pre><code class="language-javascript">Authorization: Bearer jwt_token_here
</code></pre>
<p>The important difference here is that the server is not storing authentication state for every user separately like sessions do. The token itself contains the information required for authentication. This is why JWT authentication is called stateless authentication because the server does not need to remember users separately between requests.</p>
<h2>Stateful vs Stateless Authentication</h2>
<p>This is one of the most important concepts to understand while learning authentication because most confusion around sessions and JWT comes from here itself. In stateful authentication, the server stores authentication-related data and remembers users between requests. Sessions are the most common example of this approach. The server keeps track of logged-in users and validates requests based on data stored on the server side itself.</p>
<p>In stateless authentication, the server does not store login state separately for every user. Instead, every request contains everything required for authentication. JWT is the most common example here. The server only verifies the token and does not need to remember users separately in memory or database for authentication purposes. Once this difference becomes clear, understanding authentication flows becomes much easier.</p>
<h2>Sessions vs JWT</h2>
<p>This is where most confusion usually happens because people constantly ask which one is better. But honestly, both are useful depending on the type of project you are building and the kind of architecture you are working with. Sessions are often simpler to manage for traditional applications, whereas JWT becomes useful when frontend and backend are separated or multiple services need authentication handling.</p>
<table>
<thead>
<tr>
<th>Feature</th>
<th>Sessions</th>
<th>JWT</th>
</tr>
</thead>
<tbody><tr>
<td>Authentication Type</td>
<td>Stateful</td>
<td>Stateless</td>
</tr>
<tr>
<td>Data Stored Where</td>
<td>Server</td>
<td>Client Token</td>
</tr>
<tr>
<td>Server Memory Usage</td>
<td>Higher</td>
<td>Lower</td>
</tr>
<tr>
<td>Easy Logout Handling</td>
<td>Yes</td>
<td>Slightly harder</td>
</tr>
<tr>
<td>Token Size</td>
<td>Small</td>
<td>Bigger</td>
</tr>
<tr>
<td>Scalability</td>
<td>Harder at large scale</td>
<td>Easier</td>
</tr>
<tr>
<td>Common Storage</td>
<td>Cookies</td>
<td>localStorage / Cookies</td>
</tr>
<tr>
<td>Revoking Access</td>
<td>Easy</td>
<td>Requires extra handling</td>
</tr>
<tr>
<td>Common Usage</td>
<td>Traditional web apps</td>
<td>APIs, mobile apps</td>
</tr>
</tbody></table>
<p>The main thing to understand is not which one is universally better, but rather which one fits your project requirements properly. In real-world applications, both are still heavily used depending on scalability requirements, infrastructure, frontend architecture, and security handling preferences.</p>
<h2>Session Authentication Flow</h2>
<p>In session-based authentication, the client first sends a login request to the server. The server then creates a session and stores it internally. After that, the server sends a session ID back to the browser, usually through cookies. The browser stores that cookie and automatically attaches it with future requests. Whenever a request reaches the server, the server validates the session ID and maps it to the stored session data before authenticating the request.</p>
<pre><code class="language-javascript">Client → Login Request → Server
Server → Creates Session
Server → Sends Session ID Cookie
Browser → Stores Cookie
Browser → Sends Cookie On Every Request
Server → Validates Session
</code></pre>
<p>The actual authentication state exists on the server itself, which is why this approach is called stateful authentication.</p>
<h2>JWT Authentication Flow</h2>
<p>In JWT authentication, the client first sends login credentials to the server. The server validates them and generates a JWT token instead of creating a session. That token is sent back to the client and stored on the client side. For future requests, the client manually sends the token, generally through the Authorization header. The server then verifies the token signature and authenticates the request if the token is valid.</p>
<pre><code class="language-javascript">Client → Login Request → Server
Server → Generates JWT
Server → Sends JWT
Client → Stores Token
Client → Sends Token In Authorization Header
Server → Verifies JWT Signature
</code></pre>
<p>Here the token itself carries authentication information, which removes the need for maintaining server-side authentication state separately.</p>
<h2>Where Cookies Fit In JWT?</h2>
<p>This part confuses many people because tutorials often compare cookies and JWT as if they are direct competitors. Cookies and JWT are not competitors at all. JWT can also be stored inside cookies. That means sessions often use cookies, and JWT can also use cookies depending on implementation preferences. Cookies are simply storage or transport mechanisms. The real comparison is session-based authentication versus token-based authentication using JWT. Once this distinction becomes clear, a lot of confusion disappears automatically.</p>
<h2>When Should You Use Sessions?</h2>
<p>Sessions are still very commonly used in production systems. They work especially well when you have traditional server-rendered applications and want simpler authentication handling. They also make logout handling easier because invalidating a session on the server side is straightforward. Sessions are useful when you want stronger control over active users and when your application does not require highly distributed stateless scaling architecture. Frameworks like Express sessions, Django sessions, and Laravel sessions heavily use session-based authentication even today because for many projects, sessions are still completely fine and practical.</p>
<h2>When Should You Use JWT?</h2>
<p>JWT becomes useful when you are building APIs, mobile applications, or systems where frontend and backend are separated. It is also useful when multiple services need authentication verification without relying on centralized session storage. JWT fits very naturally into MERN stack applications because frontend and backend usually operate independently. Stateless authentication also makes horizontal scaling easier since servers do not need to maintain separate session storage for every logged-in user.</p>
<h2>One Important Misconception</h2>
<p>A lot of tutorials on the internet make JWT sound automatically superior to sessions, but that is not really true. JWT solves specific problems, and sessions solve specific problems. If your application does not actually require stateless authentication, sessions may even end up being simpler and easier to manage properly. In many real-world systems, companies even use hybrid approaches depending on different requirements inside different services. So instead of trying to find one universally better solution, it is much better to understand the strengths and tradeoffs of both approaches properly.</p>
<h2>Final Thoughts</h2>
<p>Understanding authentication becomes much easier once you stop mixing sessions, cookies, and JWT together. Cookies are simply storage mechanisms. Sessions are server-side stateful authentication. JWT is token-based stateless authentication. Both sessions and JWT are widely used in production systems and both solve valid real-world problems depending on project architecture and scalability requirements.</p>
<p>The important thing is not memorizing definitions. The important thing is understanding where authentication state lives and how the server verifies the user on every request. Once that clicks properly, the whole authentication flow starts making much more sense and choosing between sessions and JWT also becomes much easier.</p>
<p>Hope this helps, this is a bit longer than what I write generally but it was important to explain things in very easy manner and in detail instead of using jargons and by-passing things.</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Virtual DOM in React Without the Usual Confusion]]></title><description><![CDATA[If you have worked with React even for a few days, you have probably heard people saying things like: “React uses Virtual DOM, that’s why it is fast.” But most of the time nobody actually explains wha]]></description><link>https://blogs.gaurangpods.com/react-virtual-dom</link><guid isPermaLink="true">https://blogs.gaurangpods.com/react-virtual-dom</guid><category><![CDATA[React]]></category><category><![CDATA[react js]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[DOM]]></category><dc:creator><![CDATA[Gaurang Nagar]]></dc:creator><pubDate>Thu, 07 May 2026 22:18:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950f282d7c55cc3d6748277/3c6fc039-834a-43b9-bc00-fabfc8a6b87c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you have worked with React even for a few days, you have probably heard people saying things like: “React uses Virtual DOM, that’s why it is fast.” But most of the time nobody actually explains what is happening behind the scenes in a simple way.<br />When I initially started learning React, I knew that Virtual DOM existed, but I never properly understood what problem it was solving. I was just hearing terms like diffing, reconciliation, re-rendering, tree comparison, and honestly everything started sounding more complicated than it needed to be.<br />So in this blog, let’s understand the Virtual DOM properly from scratch. Not the interview-definition version. The actual mental model of what happens when React updates the UI.</p>
<h2>The Problem With Direct DOM Manipulation</h2>
<p>Before understanding Virtual DOM, first we need to understand why React even needed it. Updating the Real DOM directly is expensive. By expensive, I do not mean money. I mean performance-wise.</p>
<p>The browser has to do a lot of work whenever the DOM changes. Things like:</p>
<ul>
<li><p>Recalculating layout</p>
</li>
<li><p>Repainting elements</p>
</li>
<li><p>Re-rendering parts of the UI</p>
</li>
<li><p>Reflowing the page structure</p>
</li>
</ul>
<p>And if updates happen very frequently, direct DOM manipulation can become slow very quickly. Imagine having a huge UI with hundreds of elements and changing things manually every time state changes.</p>
<pre><code class="language-javascript">const heading = document.getElementById("title");

heading.innerText = "New Title";
</code></pre>
<p>This looks harmless. But when applications become large and updates happen continuously, manually updating the DOM becomes difficult to manage and expensive for the browser. This is the exact problem React tries to solve.</p>
<h2>Real DOM vs Virtual DOM</h2>
<p>The Real DOM is the actual DOM that exists inside the browser. It is what the browser uses to display your webpage visually. Whenever something changes in the UI, the browser updates the Real DOM.<br />The Virtual DOM, on the other hand, is just a lightweight JavaScript representation of the Real DOM. It is not an actual browser DOM. It is basically a JavaScript object tree that React creates and manages internally.<br />A very simplified example looks something like this:</p>
<pre><code class="language-javascript">const virtualDOM = {
  type: "h1",
  props: {
    children: "Hello"
  }
};
</code></pre>
<p>React uses these lightweight objects because comparing JavaScript objects is much faster than directly touching the Real DOM repeatedly. So instead of updating the Real DOM immediately every time something changes, React first works with this Virtual DOM representation.</p>
<h2>What Happens During Initial Render</h2>
<p>Now let’s understand the actual flow. When a React application renders for the very first time, React creates a Virtual DOM tree for the entire component structure.</p>
<p>Suppose we have this component:</p>
<pre><code class="language-javascript">function App() {
  return (
    &lt;div&gt;
      &lt;h1&gt;Hello&lt;/h1&gt;
      &lt;p&gt;Welcome&lt;/p&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<p>React converts this into a Virtual DOM tree internally. Something conceptually like this:</p>
<pre><code class="language-javascript">{
  type: "div",
  children: [
    {
      type: "h1",
      children: ["Hello"]
    },
    {
      type: "p",
      children: ["Welcome"]
    }
  ]
}
</code></pre>
<p>After creating this Virtual DOM tree, React uses it to build the actual Real DOM elements inside the browser. So the flow becomes:<br />Component → Virtual DOM → Real DOM<br />At this point, the UI becomes visible on the screen.</p>
<h2>What Happens When State or Props Change</h2>
<p>Now comes the important part. Suppose we have a component like this:</p>
<pre><code class="language-javascript">import { useState } from "react";

function Counter() {
  const [count, setCount] = useState(0);

  return (
    &lt;div&gt;
      &lt;h1&gt;{count}&lt;/h1&gt;

      &lt;button onClick={() =&gt; setCount(count + 1)}&gt;
        Increment
      &lt;/button&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<p>Initially, count is 0. React creates a Virtual DOM tree for it and renders the UI.</p>
<p>Now when the button is clicked:</p>
<pre><code class="language-javascript">setCount(count + 1);
</code></pre>
<p>React understands that state has changed. And this triggers a re-render.</p>
<p>A lot of beginners think React directly updates the browser DOM here. That is not what happens. Instead, React creates an entirely new Virtual DOM tree again.</p>
<p>This new tree represents what the UI should look like after the state update. So now React has:</p>
<ul>
<li><p>Old Virtual DOM tree</p>
</li>
<li><p>New Virtual DOM tree</p>
</li>
</ul>
<p>And now comes the core concept.</p>
<h2>What is Diffing in React</h2>
<p>Diffing simply means comparing the old Virtual DOM tree with the new Virtual DOM tree. React checks: “What actually changed?” This entire comparison process is called reconciliation.<br />The goal is simple: Find the minimum number of changes needed to update the UI.For example : - Before update:</p>
<pre><code class="language-javascript">&lt;h1&gt;0&lt;/h1&gt;
</code></pre>
<p>After update:</p>
<pre><code class="language-javascript">&lt;h1&gt;1&lt;/h1&gt;
</code></pre>
<p>React compares both trees and notices: Only the text inside h1 changed.<br />The div did not change. The button did not change. Everything else stayed the same.<br />So React updates only that specific part. This is the biggest advantage. Instead of rebuilding the entire UI, React updates only the changed nodes.</p>
<h2>How React Applies Minimal Changes</h2>
<p>Once React finishes comparing the trees, it creates something called an update patch internally. This patch contains only the necessary changes.<br />Then React updates the Real DOM with only those specific modifications. So instead of doing something like: “Destroy everything and rebuild the entire page” React does: “Only update the exact thing that changed”<br />That is why React applications feel fast and efficient. Especially in large applications where updates happen continuously.</p>
<h2>Why Virtual DOM Improves Performance</h2>
<p>A common misconception is that Virtual DOM itself is magically fast. That is not entirely true.</p>
<p>The actual benefit comes from minimizing expensive Real DOM operations. React avoids unnecessary DOM updates by:</p>
<ul>
<li><p>Comparing old and new Virtual DOM trees</p>
</li>
<li><p>Detecting only changed parts</p>
</li>
<li><p>Updating only those nodes in the Real DOM</p>
</li>
</ul>
<p>Since DOM manipulation is expensive but JavaScript object comparison is relatively cheap, this approach improves performance significantly. Especially for dynamic UIs.</p>
<h2>The Overall React Update Flow</h2>
<p>At a high level, React’s update lifecycle looks like this:<br />State/Props Change → New Virtual DOM Created → Diffing Happens → Minimal Changes Identified → Real DOM Updated<br />This entire cycle happens very quickly behind the scenes. Most of the time, we do not even notice it happening.<br />And honestly, this is one of the reasons React became so popular. Developers can focus on describing the UI instead of manually updating DOM elements every time something changes.</p>
<h2>One Important Thing to Understand</h2>
<p>A re-render does not mean the entire Real DOM gets rebuilt. This is one of the most misunderstood things among beginners.<br />Re-rendering mainly means: React creates a new Virtual DOM tree again.<br />After that, React compares it with the previous one and updates only the necessary parts in the Real DOM. So even if a component re-renders, React still tries to minimize actual browser DOM changes.<br />That is the entire idea behind reconciliation.</p>
<h2>Final Thoughts</h2>
<p>Virtual DOM is not some magical browser feature. It is simply a smart strategy React uses to make UI updates efficient.<br />The important thing is not memorizing definitions like: “Virtual DOM is a lightweight copy of the Real DOM.”<br />The real understanding comes from knowing the flow:</p>
<ul>
<li><p>React creates Virtual DOM</p>
</li>
<li><p>State changes trigger re-render</p>
</li>
<li><p>New Virtual DOM gets created</p>
</li>
<li><p>React compares old vs new trees</p>
</li>
<li><p>Only necessary updates are applied to the Real DOM</p>
</li>
</ul>
<p>Once this mental model becomes clear, a lot of React concepts start making much more sense automatically.</p>
<p>I hope this simple explanation in easy language would have made the virtual DOM concept and how React works, clear to you.</p>
]]></content:encoded></item><item><title><![CDATA[Spread vs Rest Operators in JavaScript]]></title><description><![CDATA[If you’ve been writing modern JavaScript, you must have seen three dots being used in different places. Sometimes it is used to expand values, sometimes to collect values, and at first it feels like t]]></description><link>https://blogs.gaurangpods.com/spread-vs-rest-operators-in-js</link><guid isPermaLink="true">https://blogs.gaurangpods.com/spread-vs-rest-operators-in-js</guid><category><![CDATA[js]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[beginner]]></category><category><![CDATA[Operators]]></category><dc:creator><![CDATA[Gaurang Nagar]]></dc:creator><pubDate>Thu, 30 Apr 2026 23:02:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950f282d7c55cc3d6748277/be31c083-7680-4f23-bec6-ebc7ea0f96d7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you’ve been writing modern JavaScript, you must have seen three dots being used in different places. Sometimes it is used to expand values, sometimes to collect values, and at first it feels like the same thing doing different jobs. That is where the confusion usually starts. The syntax looks the same, but the behavior depends on how and where it is used.<br />So the idea is simple. Spread is used to expand values, and rest is used to collect values. Same syntax, different purpose based on context.</p>
<h2>What spread operator does</h2>
<p>Spread operator is used to take values from an iterable like an array or object and expand them into individual elements. It basically opens up the structure and places the values where needed.</p>
<pre><code class="language-javascript">const numbers = [10, 20, 30];

const newNumbers = [...numbers];

console.log(newNumbers);

// Output:
// [10, 20, 30]
</code></pre>
<p>Here, the values from numbers are expanded into newNumbers. It is not referencing the same array, it creates a new one with copied values.</p>
<p>Spread is very useful when we want to copy or combine arrays.</p>
<pre><code class="language-javascript">const arr1 = [1, 2];
const arr2 = [3, 4];

const combined = [...arr1, ...arr2];

console.log(combined);

// Output:
// [1, 2, 3, 4]
</code></pre>
<p>Here both arrays are expanded and merged into one.</p>
<h2>Using spread with objects</h2>
<p>Spread also works with objects. It helps in copying properties or merging objects.</p>
<pre><code class="language-javascript">const user = {
  name: "Gaurang",
  age: 21
};

const updatedUser = {
  ...user,
  role: "Developer"
};

console.log(updatedUser);

// Output:
// { name: "Gaurang", age: 21, role: "Developer" }
</code></pre>
<p>Here all properties from user are expanded into updatedUser, and then a new property is added.</p>
<h2>What rest operator does</h2>
<p>Rest operator does the opposite of spread. Instead of expanding values, it collects multiple values into a single variable. It is commonly used in function parameters or destructuring.</p>
<pre><code class="language-javascript">function sum(...numbers) {
  console.log(numbers);
}

sum(10, 20, 30);

// Output:
// [10, 20, 30]
</code></pre>
<p>Here, all arguments are collected into the numbers array.<br />Rest can also be used in array destructuring.</p>
<pre><code class="language-javascript">const numbers = [10, 20, 30, 40];

const [first, ...rest] = numbers;

console.log(first);
console.log(rest);

// Output:
// 10
// [20, 30, 40]
</code></pre>
<p>Here first gets 10, and the remaining values are collected into rest.</p>
<h2>Differences between spread and rest</h2>
<p>Even though both use the same three dots syntax, their behavior is different based on usage. Spread is used when we want to expand values, rest is used when we want to collect values.<br />Spread is usually seen on the right side when assigning or passing values, while rest is usually seen on the left side when receiving values.</p>
<h2>Practical use cases</h2>
<p>Spread is commonly used when copying arrays or objects, merging multiple arrays, or passing elements as individual arguments to functions.</p>
<pre><code class="language-javascript">const numbers = [1, 2, 3];

function add(a, b, c) {
  console.log(a + b + c);
}

add(...numbers);

// Output:
// 6
</code></pre>
<p>Here spread expands the array into individual arguments.<br />Rest is useful when we do not know how many arguments will be passed and we want to handle them as a group.</p>
<pre><code class="language-javascript">function logAll(...values) {
  console.log(values);
}

logAll("a", "b", "c");

// Output:
// ["a", "b", "c"]
</code></pre>
<p>It collects all arguments into a single array.</p>
<h2>Final clarity</h2>
<p>Spread and rest use the same syntax but solve opposite problems. Spread expands values from arrays or objects, while rest collects multiple values into one variable. Once you focus on whether values are being expanded or collected, it becomes easy to understand where to use each of them.</p>
]]></content:encoded></item><item><title><![CDATA[Map and Set in JavaScript]]></title><description><![CDATA[If you’ve been working with JavaScript, you’ve mostly used objects and arrays to store data. Objects are used for key value pairs and arrays are used for lists. That works fine in most cases, but ther]]></description><link>https://blogs.gaurangpods.com/map-and-set-in-js</link><guid isPermaLink="true">https://blogs.gaurangpods.com/map-and-set-in-js</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[map]]></category><category><![CDATA[js]]></category><category><![CDATA[basics]]></category><dc:creator><![CDATA[Gaurang Nagar]]></dc:creator><pubDate>Thu, 30 Apr 2026 20:06:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950f282d7c55cc3d6748277/3b2ac94d-ebdc-4e43-9795-a626f057295f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you’ve been working with JavaScript, you’ve mostly used objects and arrays to store data. Objects are used for key value pairs and arrays are used for lists. That works fine in most cases, but there are some limitations with both. That is where Map and Set come into picture. They are built in data structures that solve some specific problems which objects and arrays do not handle well.<br />So before jumping into Map and Set directly, it is important to understand why they even exist. Objects restrict keys to strings or symbols, and arrays allow duplicate values. In many real scenarios, we want more flexibility in keys or we want to ensure uniqueness in data. That is exactly what Map and Set help with.</p>
<h2>What Map is</h2>
<p>Map is a collection of key value pairs, similar to objects, but with more flexibility. In Map, keys can be of any type, not just strings. That means you can use numbers, objects, or even functions as keys.</p>
<pre><code class="language-javascript">const map = new Map();

map.set("name", "Gaurang");
map.set(1, "One");

console.log(map.get("name"));
console.log(map.get(1));
</code></pre>
<p>Here we are storing values using different types of keys. This is something that objects do not support directly.<br />Another important thing is that Map maintains insertion order, so the order in which you add entries is preserved.</p>
<h2>What Set is</h2>
<p>Set is a collection of unique values. It automatically removes duplicates, which is something arrays do not do.</p>
<pre><code class="language-javascript">const set = new Set();

set.add(10);
set.add(20);
set.add(10);

console.log(set);
</code></pre>
<p>Even though we added 10 twice, it will only be stored once. That is because Set only keeps unique values.<br />This makes Set very useful when you want to remove duplicates from a list or ensure that only unique values are stored.</p>
<h2>Problem with traditional objects</h2>
<p>Objects are useful, but they have limitations. Keys are always treated as strings, even if you use numbers. Also, objects are not designed for frequent additions and deletions in the same way Map is.</p>
<pre><code class="language-javascript">const obj = {};

obj[1] = "One";
obj["1"] = "Duplicate";

console.log(obj);
</code></pre>
<p>Here both keys will be treated the same, because object keys are converted to strings.</p>
<h2>Map vs Object</h2>
<p>Map provides better flexibility compared to objects when it comes to key value storage. Keys in Map can be of any type, whereas in objects they are limited. Map also has built in methods like set, get, has, and delete which make operations more structured.</p>
<pre><code class="language-javascript">const map = new Map();

map.set({ id: 1 }, "User1");
map.set({ id: 2 }, "User2");

console.log(map.size);
</code></pre>
<p>This kind of usage is not possible with objects in a reliable way because objects do not handle non string keys properly.</p>
<h2>Problem with arrays</h2>
<p>Arrays allow duplicate values, which is not always desired. If you are storing data where uniqueness matters, arrays require extra logic to handle duplicates.</p>
<pre><code class="language-javascript">const numbers = [10, 20, 10, 30];

console.log(numbers);
</code></pre>
<p>Here duplicates are allowed, and you would need to manually filter them out if required.</p>
<h2>Set vs Array</h2>
<p>Set solves this problem by ensuring uniqueness automatically. It stores only unique values and ignores duplicates.</p>
<pre><code class="language-javascript">const numbers = new Set([10, 20, 10, 30]);

console.log(numbers);
</code></pre>
<p>Now you do not need extra logic to remove duplicates. Set handles it internally.</p>
<h2>When to use Map and Set</h2>
<p>Map is useful when you need flexible key value storage and when keys are not just strings. It is also helpful when you need to maintain insertion order and perform frequent operations like add, delete, and lookup.<br />Set is useful when you want to store unique values and avoid duplicates without writing extra logic. It is commonly used when working with lists where repetition is not allowed.</p>
<h2>Final clarity</h2>
<p>Map and Set are alternatives to objects and arrays for specific use cases. Map improves key value handling by allowing any type of keys and providing better control over operations. Set ensures uniqueness and simplifies working with collections of values where duplicates are not needed.<br />So instead of forcing everything into objects and arrays, using Map and Set where they fit makes the code cleaner and more efficient.</p>
]]></content:encoded></item><item><title><![CDATA[Understanding destructuring in JavaScript]]></title><description><![CDATA[If you’ve been writing JavaScript, you must have seen cases where we take values out of objects or arrays and assign them to variables. Usually, we do it one by one, which works fine but becomes repet]]></description><link>https://blogs.gaurangpods.com/understanding-destructuring-in-js</link><guid isPermaLink="true">https://blogs.gaurangpods.com/understanding-destructuring-in-js</guid><category><![CDATA[js]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[basics]]></category><category><![CDATA[array]]></category><category><![CDATA[Objects]]></category><dc:creator><![CDATA[Gaurang Nagar]]></dc:creator><pubDate>Thu, 30 Apr 2026 19:38:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950f282d7c55cc3d6748277/e3a1432b-21d5-40b2-b9d9-db27f6a8ccc7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you’ve been writing JavaScript, you must have seen cases where we take values out of objects or arrays and assign them to variables. Usually, we do it one by one, which works fine but becomes repetitive very quickly. Destructuring is a cleaner way of doing the same thing, where we can extract values directly into variables in a single line.<br />So destructuring simply means pulling out values from arrays or objects and assigning them to variables in a more concise way. It does not change the data, it just makes extraction easier and cleaner.</p>
<h2>What destructuring means ?</h2>
<p>Normally, when we access values from an object or array, we do it step by step. Destructuring allows us to do that in a shorter and more readable way by matching structure on the left side.</p>
<p>Let’s first see how things are done without destructuring.</p>
<pre><code class="language-javascript">const user = {
  name: "Gaurang",
  age: 21,
  role: "Developer"
};

const name = user.name;
const age = user.age;
const role = user.role;

console.log(name, age, role);
</code></pre>
<p>Now the same thing using destructuring:</p>
<pre><code class="language-javascript">const user = {
  name: "Gaurang",
  age: 21,
  role: "Developer"
};

const { name, age, role } = user;

console.log(name, age, role);
</code></pre>
<p>Here, instead of writing multiple lines, we extracted everything in one go.</p>
<h2>Destructuring arrays</h2>
<p>Destructuring also works with arrays. In arrays, the position matters instead of the property name.</p>
<pre><code class="language-javascript">const numbers = [10, 20, 30];

const first = numbers[0];
const second = numbers[1];
const third = numbers[2];

console.log(first, second, third);
</code></pre>
<p>Now using destructuring:</p>
<pre><code class="language-javascript">const numbers = [10, 20, 30];

const [first, second, third] = numbers;

console.log(first, second, third);
</code></pre>
<p>Here, the first variable gets the first value, second gets the second, and so on. It directly maps based on index.</p>
<h2>Destructuring objects</h2>
<p>In objects, destructuring works based on property names, not position.</p>
<pre><code class="language-javascript">const player = {
  name: "Virat",
  role: "Batter",
  team: "India"
};

const { name, role } = player;

console.log(name, role);
</code></pre>
<p>Here, variables name and role are created and assigned from the object. If the property names match, destructuring becomes very straightforward.</p>
<h2>Default values</h2>
<p>There are cases where some values might not exist. In those situations, destructuring allows us to assign default values.</p>
<pre><code class="language-javascript">const user = {
  name: "Gaurang"
};

const { name, age = 20 } = user;

console.log(name, age);
</code></pre>
<p>Here, age does not exist in the object, so it takes the default value 20. This helps avoid undefined values and makes code safer.</p>
<h2>Before vs after destructuring</h2>
<p>Without destructuring, extracting multiple values leads to repetitive code. With destructuring, the same work becomes shorter and more readable.</p>
<pre><code class="language-javascript">const product = {
  title: "Laptop",
  price: 50000,
  brand: "HP"
};

const title = product.title;
const price = product.price;
const brand = product.brand;

console.log(title, price, brand);
</code></pre>
<pre><code class="language-javascript">const product = {
  title: "Laptop",
  price: 50000,
  brand: "HP"
};

const { title, price, brand } = product;

console.log(title, price, brand);
</code></pre>
<p>The second version is cleaner and reduces repetition.</p>
<h2>Benefits of destructuring</h2>
<p>Destructuring helps in writing less code, improves readability, and makes it easier to work with objects and arrays. It is especially useful when dealing with function parameters, API responses, or any structured data.<br />It also makes the intent clearer, since we can directly see what values are being extracted instead of scanning multiple lines.</p>
<h2>Final clarity</h2>
<p>Destructuring is just a cleaner way to extract values from arrays and objects. Arrays use position based extraction, objects use property names, and default values help handle missing data. It does not introduce new behavior, it just simplifies existing patterns and makes code easier to read and maintain.</p>
]]></content:encoded></item><item><title><![CDATA[Error Handling in JavaScript: Try, Catch, Finally]]></title><description><![CDATA[While writing JavaScript, you will definitely run into situations where something breaks at runtime. It might be accessing a property that does not exist, parsing invalid data, or calling something th]]></description><link>https://blogs.gaurangpods.com/error-handling-in-js</link><guid isPermaLink="true">https://blogs.gaurangpods.com/error-handling-in-js</guid><category><![CDATA[js]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[error handling]]></category><category><![CDATA[basics]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Gaurang Nagar]]></dc:creator><pubDate>Thu, 30 Apr 2026 18:11:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950f282d7c55cc3d6748277/c2c02c15-25d4-4baa-934c-263bd0e86409.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>While writing JavaScript, you will definitely run into situations where something breaks at runtime. It might be accessing a property that does not exist, parsing invalid data, or calling something that is not a function. These are called errors, and if not handled properly, they can stop your entire program from executing further. That is why error handling becomes important, not just to prevent crashes, but also to make your application behave in a controlled way even when something goes wrong.</p>
<p>Let’s start with a very basic runtime error so that the problem becomes clear.</p>
<pre><code class="language-javascript">console.log("Start");

let user = undefined;
console.log(user.name);

console.log("End");
</code></pre>
<p>Here, the moment JavaScript tries to access user.name, it throws an error because user is undefined. Because of this, the program stops immediately and "End" never gets printed. This is what happens when errors are not handled, execution breaks in between.</p>
<h2>What errors are in JavaScript</h2>
<p>Errors are situations where the code cannot execute as expected. These are usually runtime issues, meaning they occur when the code is running, not when it is written. JavaScript throws these errors automatically when it encounters something invalid, like accessing properties on undefined, calling something that is not a function, or invalid operations.<br />If we do not handle these errors, they bubble up and stop execution, which is not ideal in most real applications.</p>
<h2>Using try and catch blocks</h2>
<p>To handle such situations, JavaScript provides try and catch. The idea is simple, we try to execute a block of code, and if any error occurs inside it, we catch it and handle it.</p>
<pre><code class="language-javascript">console.log("Start");

try {
  let user = undefined;
  console.log(user.name);
} catch (error) {
  console.log("Something went wrong");
}

console.log("End");
</code></pre>
<p>Now instead of breaking the program, the error is caught, and the program continues executing. So "End" will be printed.<br />This is called graceful failure. Instead of crashing, we handle the issue and move forward.</p>
<h2>The finally block</h2>
<p>There are situations where we want some code to run no matter what, whether an error occurs or not. That is where finally comes in.</p>
<pre><code class="language-javascript">try {
  console.log("Inside try");
} catch (error) {
  console.log("Inside catch");
} finally {
  console.log("This always runs");
}
</code></pre>
<p>The finally block always executes. Even if there is no error, or even if there is an error and it is caught, finally will still run. This is useful for cleanup tasks or closing resources.</p>
<h2>Throwing custom errors</h2>
<p>JavaScript also allows us to create our own errors using throw. This is useful when we want to enforce certain conditions manually.</p>
<pre><code class="language-javascript">function withdraw(amount) {
  if (amount &gt; 1000) {
    throw new Error("Limit exceeded");
  }
  console.log("Withdrawal successful");
}

try {
  withdraw(2000);
} catch (error) {
  console.log(error.message);
}
</code></pre>
<p>Here, we are manually throwing an error when a condition is not met. This helps in controlling the flow and making sure invalid operations are not silently ignored.</p>
<h2>Why error handling matters</h2>
<p>Error handling is important because it prevents your application from crashing unexpectedly. It allows you to show proper messages, log issues for debugging, and keep the rest of the application running.<br />Without error handling, even a small issue can break the entire flow. With proper handling, you can isolate the problem and deal with it in a controlled way.<br />It also helps a lot during debugging. Instead of getting random crashes, you get clear points where things failed, which makes it easier to fix issues.</p>
<h2>Final clarity</h2>
<p>Errors are a natural part of programming, especially in JavaScript where many things happen at runtime. Try and catch help in handling these errors gracefully, finally ensures that certain code always runs, and throw allows us to create our own errors when needed.<br />So instead of letting your program break, you take control of how it behaves when something goes wrong, and that is the main idea behind error handling in JavaScript.</p>
]]></content:encoded></item><item><title><![CDATA[Async Code in Node.js: Callbacks and Promises]]></title><description><![CDATA[If you’ve been working with JavaScript, especially Node.js, you must have noticed that a lot of things are asynchronous by default. Reading files, making API calls, database operations, all of these d]]></description><link>https://blogs.gaurangpods.com/callbacks-and-promises-in-node</link><guid isPermaLink="true">https://blogs.gaurangpods.com/callbacks-and-promises-in-node</guid><category><![CDATA[Node.js]]></category><category><![CDATA[js]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[asynchronous]]></category><category><![CDATA[basics]]></category><dc:creator><![CDATA[Gaurang Nagar]]></dc:creator><pubDate>Thu, 30 Apr 2026 14:59:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950f282d7c55cc3d6748277/5c05fd52-e946-4f0a-8a04-f9b575a509a0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you’ve been working with JavaScript, especially Node.js, you must have noticed that a lot of things are asynchronous by default. Reading files, making API calls, database operations, all of these do not block execution. This is not accidental, this is how Node.js is designed to work efficiently. Since JavaScript runs on a single thread, Node.js relies heavily on asynchronous behavior so that one slow operation does not stop everything else from running.<br />So the reason async code exists in Node.js is simple, to avoid blocking. If every file read or database call was synchronous, the server would get stuck handling one request at a time, which would make it slow and inefficient. Async behavior allows Node.js to handle multiple operations without waiting for each one to finish before moving ahead.</p>
<h2>Starting with a file reading example</h2>
<p>Let’s take a very simple example of reading a file. In Node.js, we usually use asynchronous file reading so that the program does not block.</p>
<pre><code class="language-javascript">const fs = require("fs");

console.log("Start");

fs.readFile("data.txt", "utf-8", (err, data) =&gt; {
  if (err) {
    console.log("Error reading file");
    return;
  }
  console.log("File content:", data);
});

console.log("End");
</code></pre>
<p>Here, even though the file is being read in between, the output will be:</p>
<p>**Start  </p>
<p>**End  </p>
<p>*File content: ...</p>
<p>This happens because file reading is asynchronous. Node.js starts the operation and moves ahead, and once the data is ready, the callback function is executed.</p>
<h2>Callback based async execution</h2>
<p>Callbacks are one of the earliest ways to handle asynchronous code in JavaScript. A callback is simply a function that is passed as an argument and is executed later when the async task is completed.<br />In the previous example, the function inside readFile is the callback. It runs only after the file has been read.<br />The flow is simple, start the task, continue execution, and once the task finishes, run the callback. This allows non blocking behavior.</p>
<h2>Problem with nested callbacks</h2>
<p>The problem starts when we have multiple async operations that depend on each other. Then callbacks start getting nested inside each other, which makes the code harder to read and maintain.</p>
<pre><code class="language-javascript">const fs = require("fs");

fs.readFile("file1.txt", "utf-8", (err, data1) =&gt; {
  if (err) return console.log(err);

  fs.readFile("file2.txt", "utf-8", (err, data2) =&gt; {
    if (err) return console.log(err);

    fs.readFile("file3.txt", "utf-8", (err, data3) =&gt; {
      if (err) return console.log(err);

      console.log(data1, data2, data3);
    });
  });
});
</code></pre>
<p>This structure keeps going deeper as more operations are added. It becomes difficult to follow the flow, handle errors properly, and debug issues. This is commonly referred to as callback nesting, and it quickly becomes messy.</p>
<h2>Promise based async handling</h2>
<p>To solve the readability issue of callbacks, promises were introduced. A promise represents a value that may be available now, later, or never. Instead of passing callbacks, we return promises and handle results using then and catch.</p>
<p>Let’s convert the file reading example into promise based code.</p>
<pre><code class="language-javascript">const fs = require("fs").promises;

console.log("Start");

fs.readFile("data.txt", "utf-8")
  .then((data) =&gt; {
    console.log("File content:", data);
  })
  .catch((err) =&gt; {
    console.log("Error reading file");
  });

console.log("End");
</code></pre>
<p>The behavior is still asynchronous, but the structure is cleaner. Instead of nesting, we chain operations.</p>
<h2>Handling multiple operations with promises</h2>
<p>The earlier nested example can now be written in a much cleaner way.</p>
<pre><code class="language-javascript">const fs = require("fs").promises;

fs.readFile("file1.txt", "utf-8")
  .then((data1) =&gt; {
    return fs.readFile("file2.txt", "utf-8").then((data2) =&gt; {
      return { data1, data2 };
    });
  })
  .then(({ data1, data2 }) =&gt; {
    return fs.readFile("file3.txt", "utf-8").then((data3) =&gt; {
      console.log(data1, data2, data3);
    });
  })
  .catch((err) =&gt; {
    console.log(err);
  });
</code></pre>
<p>Even though this is still not perfect, it is more readable compared to deeply nested callbacks.</p>
<h2>Benefits of promises</h2>
<p>Promises solve multiple issues that callbacks had. The code becomes flatter, easier to read, and error handling becomes more consistent because we can use a single catch block. It also becomes easier to chain operations and manage flow without going deep into nested structures.<br />Another advantage is that promises can be combined with async and await, which makes the code even more readable and closer to synchronous style, while still being asynchronous underneath.</p>
<h2>Final clarity</h2>
<p>Async code exists in Node.js to prevent blocking and to make efficient use of the single threaded nature of JavaScript. Callbacks were the initial way to handle async operations, but they become difficult to manage when multiple steps are involved. Promises improve this by providing a cleaner and more structured way to handle async flow.<br />So the progression becomes clear, callbacks handle async tasks but can get messy, promises improve readability and structure, and later async and await make it even simpler to write and understand.</p>
]]></content:encoded></item><item><title><![CDATA[Understanding async and await in JavaScript]]></title><description><![CDATA[If you’ve worked with asynchronous JavaScript, you must have come across promises. They solve the problem of handling async operations, but after a point, chaining multiple promises starts getting mes]]></description><link>https://blogs.gaurangpods.com/async-await-in-js</link><guid isPermaLink="true">https://blogs.gaurangpods.com/async-await-in-js</guid><category><![CDATA[asynchronous]]></category><category><![CDATA[async/await]]></category><category><![CDATA[js]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Gaurang Nagar]]></dc:creator><pubDate>Thu, 30 Apr 2026 14:25:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950f282d7c55cc3d6748277/2982b94e-8751-44ca-b93b-47ded133eaed.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you’ve worked with asynchronous JavaScript, you must have come across promises. They solve the problem of handling async operations, but after a point, chaining multiple promises starts getting messy and harder to read. That is exactly why async and await were introduced. The goal was not to replace promises, but to make working with them more readable and easier to manage.<br />So the important thing to keep in mind from the start is that async and await are just a cleaner way of writing promise based code. Internally, everything is still based on promises.</p>
<h2>Why async and await were introduced</h2>
<p>When promises were introduced, they improved things compared to callbacks, but chaining then and catch multiple times can still make code look complex. As the number of async operations increases, readability becomes an issue and debugging also gets harder.</p>
<pre><code class="language-javascript">function fetchData() {
  return new Promise((resolve) =&gt; {
    setTimeout(() =&gt; {
      resolve("Data received");
    }, 2000);
  });
}

fetchData()
  .then((data) =&gt; {
    console.log(data);
    return "Next step";
  })
  .then((res) =&gt; {
    console.log(res);
  })
  .catch((err) =&gt; {
    console.log(err);
  });
</code></pre>
<p>This works fine, but as more steps get added, it becomes harder to follow the flow. That is where async and await improve things by making the code look more like synchronous code.</p>
<h2>How async functions work</h2>
<p>An async function is just a function that always returns a promise. Even if you return a normal value, it will be wrapped inside a promise automatically.</p>
<pre><code class="language-javascript">async function greet() {
  return "Hello";
}

greet().then((res) =&gt; console.log(res));
</code></pre>
<p>Here, even though we returned a string, it is treated as a resolved promise.<br />So the key idea is that async makes a function return a promise.</p>
<h2>Await keyword concept</h2>
<p>Await is used inside async functions to pause the execution until a promise is resolved. It makes the code look like it is running step by step, even though it is still asynchronous underneath.</p>
<pre><code class="language-javascript">function fetchData() {
  return new Promise((resolve) =&gt; {
    setTimeout(() =&gt; {
      resolve("Data received");
    }, 2000);
  });
}

async function getData() {
  console.log("Start");

  const data = await fetchData();
  console.log(data);

  console.log("End");
}

getData();
</code></pre>
<p>Here, await pauses the function at that line until fetchData resolves, and then continues execution. So the flow becomes much easier to read.</p>
<h2>Comparison with promises</h2>
<p>The same example using promises would look like this:</p>
<pre><code class="language-javascript">function fetchData() {
  return new Promise((resolve) =&gt; {
    setTimeout(() =&gt; {
      resolve("Data received");
    }, 2000);
  });
}

function getData() {
  console.log("Start");

  fetchData().then((data) =&gt; {
    console.log(data);
    console.log("End");
  });
}

getData();
</code></pre>
<p>Both approaches achieve the same result, but the async and await version looks more linear and easier to follow.</p>
<h2>Error handling with async code</h2>
<p>Error handling becomes cleaner with async and await because we can use try and catch instead of chaining catch methods.</p>
<pre><code class="language-javascript">function fetchData() {
  return new Promise((resolve, reject) =&gt; {
    setTimeout(() =&gt; {
      reject("Something went wrong");
    }, 2000);
  });
}

async function getData() {
  try {
    const data = await fetchData();
    console.log(data);
  } catch (error) {
    console.log(error);
  }
}

getData();
</code></pre>
<p>This makes error handling look similar to synchronous code, which improves readability.</p>
<h2>Final clarity</h2>
<p>Async and await were introduced to make working with promises simpler and more readable. Async ensures that a function returns a promise, and await allows us to write asynchronous code in a step by step manner. Internally, everything is still based on promises, but the syntax makes it easier to understand and maintain.<br />So whenever you see async and await, think of them as a cleaner layer over promises that helps you write code that is easier to read and reason about.</p>
]]></content:encoded></item><item><title><![CDATA[Synchronous vs Asynchronous JavaScript]]></title><description><![CDATA[If you’ve been writing JavaScript for some time, you must have seen cases where code runs line by line exactly as written, and then there are cases where something starts but finishes later. That is w]]></description><link>https://blogs.gaurangpods.com/synchronous-vs-asynchronous-js</link><guid isPermaLink="true">https://blogs.gaurangpods.com/synchronous-vs-asynchronous-js</guid><category><![CDATA[js]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[asynchronous]]></category><category><![CDATA[basics]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Gaurang Nagar]]></dc:creator><pubDate>Thu, 30 Apr 2026 12:44:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950f282d7c55cc3d6748277/ee4858e6-7812-429b-bfbd-f95f1ca65d23.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you’ve been writing JavaScript for some time, you must have seen cases where code runs line by line exactly as written, and then there are cases where something starts but finishes later. That is where synchronous and asynchronous behavior comes into picture. At first it feels like JavaScript is behaving inconsistently, but in reality there is a clear pattern behind it. Once that pattern is understood, things become predictable.The idea is simple. JavaScript by default runs code in a synchronous way, which means one line executes, then the next, then the next. Nothing jumps ahead, nothing waits in between unless something explicitly introduces that behavior.</p>
<h2>What synchronous code means</h2>
<p>Synchronous code means the code runs step by step in order. Each line waits for the previous one to finish before it starts executing. There is no skipping, no delay handling, just straight execution.</p>
<pre><code class="language-javascript">console.log("Start");

function task() {
  console.log("Task running");
}

task();

console.log("End");
</code></pre>
<p>Here the output will always be:</p>
<p>**Start  </p>
<p>*Task running  </p>
<p>**End</p>
<p>This is because each line completes before moving to the next one. This is called blocking behavior because if one line takes time, everything after it has to wait.</p>
<h2>Blocking problem in synchronous code</h2>
<p>Now the issue with synchronous code shows up when a task takes time. Suppose there is a heavy operation or something that takes a few seconds, everything after it gets blocked.</p>
<pre><code class="language-javascript">console.log("Start");

function heavyTask() {
  for (let i = 0; i &lt; 1e9; i++) {}
  console.log("Heavy task done");
}

heavyTask();

console.log("End");
</code></pre>
<p>Here End will only print after the loop finishes. So the entire program is stuck until that work is done. This is what blocking looks like, nothing else can move forward.</p>
<h2>What asynchronous code means</h2>
<p>Asynchronous code allows certain tasks to run in the background without blocking the main execution. That means JavaScript can start something, move ahead, and then come back to it later when it is done.<br />So instead of waiting, it continues executing the next lines.</p>
<pre><code class="language-javascript">console.log("Start");

setTimeout(() =&gt; {
  console.log("Async task done");
}, 2000);

console.log("End");
</code></pre>
<p>The output will be:</p>
<p>**Start  </p>
<p>**End  </p>
<p>*Async task done</p>
<p>Even though the timeout was written in between, it runs later. This is non blocking behavior.</p>
<h2>Why JavaScript needs asynchronous behavior</h2>
<p>JavaScript runs on a single thread. That means it can do one thing at a time. If everything was synchronous, then any slow operation like fetching data from an API or reading a file would block the entire application.<br />Imagine clicking a button on a website and the UI freezes because it is waiting for data. That would be a bad experience. So JavaScript uses asynchronous behavior to handle these situations without stopping everything else.<br />This allows things like UI updates, user interactions, and other operations to continue smoothly.</p>
<h2>Example with API like behavior</h2>
<p>A very common real world case is fetching data. Even though we are not actually calling an API here, the behavior can be understood like this.</p>
<pre><code class="language-javascript">console.log("Start");

function fetchData() {
  setTimeout(() =&gt; {
    console.log("Data received");
  }, 2000);
}

fetchData();

console.log("End");
</code></pre>
<p>Again, the output will be:</p>
<p>**Start  </p>
<p>**End  </p>
<p>*Data received</p>
<p>So JavaScript did not wait for the data, it moved ahead and handled it later.</p>
<h2>Blocking vs non blocking clarity</h2>
<p>In synchronous code, each line blocks the next one until it finishes. In asynchronous code, certain operations are handed off and JavaScript continues executing other lines.<br />This is why asynchronous code is called non blocking, because it does not stop the flow of execution.</p>
<h2>What is happening behind the scenes</h2>
<p>When an asynchronous task like setTimeout is called, it is not executed immediately by the main thread. It is handled separately and once it is ready, it is pushed back to be executed.<br />That is why even if it appears in between, it runs after the main synchronous code finishes.</p>
<h2>Final clarity</h2>
<p>Synchronous code runs line by line and blocks execution until each step is complete. Asynchronous code allows certain tasks to run separately so that the main execution does not stop. This is important because JavaScript is single threaded and needs a way to handle slow operations without freezing everything.<br />So whenever you see something like timers, API calls, or delayed execution, that is JavaScript handling things asynchronously to keep the application responsive.</p>
]]></content:encoded></item><item><title><![CDATA[Understanding the this keyword in JavaScript]]></title><description><![CDATA[If you’ve been writing JavaScript for a while, you’ve definitely come across this keyword. At first it feels confusing because sometimes it points to one thing and sometimes to something completely di]]></description><link>https://blogs.gaurangpods.com/this-keyword-in-js</link><guid isPermaLink="true">https://blogs.gaurangpods.com/this-keyword-in-js</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[js]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><category><![CDATA[this keyword]]></category><dc:creator><![CDATA[Gaurang Nagar]]></dc:creator><pubDate>Thu, 30 Apr 2026 11:24:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950f282d7c55cc3d6748277/a47dfcf8-c8ec-49a9-803a-6b98bf617f10.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you’ve been writing JavaScript for a while, you’ve definitely come across this keyword. At first it feels confusing because sometimes it points to one thing and sometimes to something completely different. The important thing to understand is that this is not fixed, it depends on how a function is called. That is the core idea, this represents the caller of the function, not where the function is written.</p>
<p>Once this clicks, most of the confusion around this goes away. So instead of trying to memorize cases, it is better to focus on one simple idea, who is calling the function, that is what this will point to.</p>
<h2>What "this" represents</h2>
<p>"this" represents the object that is calling the function. It is decided at runtime, not at the time of writing the code. That is why the same function can behave differently depending on how it is called.<br />So if a function is called by an object, this points to that object. If it is called directly, then this depends on the environment.</p>
<h2>this in global context</h2>
<p>In the global scope, this behaves differently depending on where the code is running. In browsers, if you are in non strict mode, this refers to the global object which is window. In Node, it is different, but for simplicity, think of it as the global object in that environment.</p>
<pre><code class="language-javascript">console.log(this);
</code></pre>
<p>If you run this in a browser, you will see the window object.</p>
<h2>this inside objects</h2>
<p>When a function is defined inside an object and called using that object, "this" points to that object. This is one of the most common use cases.</p>
<pre><code class="language-javascript">const user = {
  name: "Gaurang",
  greet: function () {
    console.log("Hi, I am " + this.name);
  }
};

user.greet();
</code></pre>
<p>Here greet is called using user, so "this" points to user. That is why this.name gives "Gaurang".</p>
<h2>this inside functions</h2>
<p>Now this is where confusion usually starts. When a function is called normally, not attached to any object, "this" does not point to any custom object.</p>
<pre><code class="language-javascript">function show() {
  console.log(this);
}

show();
</code></pre>
<p>In non strict mode in browsers, "this" will point to window. In strict mode, it will be undefined. So again, there is no object calling this function, that is why "this" does not point to something meaningful here.</p>
<h2>How calling context changes this</h2>
<p>This is the most important part. The value of "this" changes based on how the function is called, not where it is defined.</p>
<pre><code class="language-javascript">const person = {
  name: "Virat",
  greet: function () {
    console.log(this.name);
  }
};

person.greet();
</code></pre>
<p>Here "this" points to person because person is calling greet.</p>
<p>Now if we take the same function and call it differently:</p>
<pre><code class="language-javascript">const person = {
  name: "Virat",
  greet: function () {
    console.log(this.name);
  }
};

const greetFunction = person.greet;
greetFunction();
</code></pre>
<p>Now the function is called without person, so "this" will not point to person anymore. In browser non strict mode, it will point to window, and since window.name is usually empty, it will not give "Virat".</p>
<p>This clearly shows that this depends on the calling context.</p>
<h2>Another simple example</h2>
<pre><code class="language-javascript">const player = {
  name: "Bumrah",
  role: "Bowler",
  introduce: function () {
    console.log(this.name + " is a " + this.role);
  }
};

player.introduce();
</code></pre>
<p>Here "this" refers to player, so the output is based on player’s data.</p>
<p>If the same function is used somewhere else without the object, the value of "this" changes.</p>
<h2>Final clarity</h2>
<p>The main idea is simple and everything revolves around it. "this" represents the caller of the function. It is not about where the function is written, it is about how the function is called. In object methods, "this" points to the object. In normal function calls, it depends on the environment. And if the calling context changes, the value of this also changes.</p>
<p>Once you start looking at this as caller based, the confusion reduces a lot and it becomes much easier to predict what this will be in any given situation.</p>
]]></content:encoded></item><item><title><![CDATA[The new Keyword in JavaScript]]></title><description><![CDATA[f you’ve been writing JavaScript for a bit, you’ve definitely seen the new keyword. At first glance, it feels simple, you write new something and you get an object. But internally, more things are hap]]></description><link>https://blogs.gaurangpods.com/new-keyword-in-js</link><guid isPermaLink="true">https://blogs.gaurangpods.com/new-keyword-in-js</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[js]]></category><category><![CDATA[basics]]></category><category><![CDATA[Objects]]></category><category><![CDATA[prototype]]></category><dc:creator><![CDATA[Gaurang Nagar]]></dc:creator><pubDate>Thu, 30 Apr 2026 09:25:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950f282d7c55cc3d6748277/4b71d13d-9d4f-4a68-9c91-65ef68f316f6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>f you’ve been writing JavaScript for a bit, you’ve definitely seen the new keyword. At first glance, it feels simple, you write new something and you get an object. But internally, more things are happening than just creating an object. So the new keyword that we use in JavaScript is basically used to create a new object. In simple terms, yes, it creates a new object, but how exactly does that happen internally is what actually matters here.</p>
<p>When we use new before a function, JavaScript performs multiple steps behind the scenes in one go. It creates a new empty object, then it links this object to the prototype of the constructor function, after that it calls the constructor function and sets this to point to that new object, then it assigns properties to this, and finally it returns that object automatically. So the important idea here is not that a new prototype is created, but that the new object gets linked to an already existing prototype, and that is what enables sharing and inheritance.</p>
<h2>Constructor functions</h2>
<p>A constructor function is just a normal function, but the difference is that we use it with new to create objects. This pattern is widely used to create multiple objects with similar structure. Instead of manually creating objects again and again, we define a constructor once and reuse it.</p>
<pre><code class="language-javascript">function Cricketer(name, role) {
  this.name = name;
  this.role = role;

  this.introduce = function () {
    console.log("Hi, I am " + this.name + " and I am a " + this.role);
  };
}

const player1 = new Cricketer("Virat Kohli", "Batter");
const player2 = new Cricketer("Jasprit Bumrah", "Bowler");
</code></pre>
<p>Both player1 and player2 are separate objects created using the same constructor, they have similar structure but different values.</p>
<h2>Object creation step by step</h2>
<p>When we write something like creating a new object using a constructor, it might look simple from outside but internally multiple things are happening in sequence. JavaScript is not just calling a function, it is preparing a complete object setup before returning it.</p>
<pre><code class="language-javascript">const player = new Cricketer("Virat Kohli", "Batter");
</code></pre>
<p>Internally, JavaScript is doing something very close to this flow, which helps in understanding what exactly is happening under the hood.</p>
<pre><code class="language-javascript">const obj = {};
Object.setPrototypeOf(obj, Cricketer.prototype);
Cricketer.call(obj, "Virat Kohli", "Batter");
return obj;
</code></pre>
<p>So the overall flow becomes constructor to new object creation, then prototype linking, then property assignment using this, and finally returning that object. This entire process is automatically handled by the new keyword.</p>
<h2>Prototype linking and inheritance</h2>
<p>Every function in JavaScript has a prototype property, and when we use new, the created object gets linked to that prototype. This is where the concept of inheritance comes into picture, not by copying data, but by linking objects.</p>
<pre><code class="language-javascript">function Cricketer(name, role) {
  this.name = name;
  this.role = role;
}

Cricketer.prototype.introduce = function () {
  console.log("Hi, I am " + this.name + " and I am a " + this.role);
};

const player1 = new Cricketer("Virat Kohli", "Batter");
const player2 = new Cricketer("Bumrah", "Bowler");
</code></pre>
<p>Here, introduce is not created separately for each object, instead both objects access it through the prototype. This means memory is used efficiently and behavior is shared. Because of this linking, the new object can access properties and methods defined on the prototype, and that is how inheritance works in this case.</p>
<h2>Relation between constructor and instance</h2>
<p>The relation is quite straightforward once seen clearly. The constructor acts as a blueprint which defines what structure and behavior an object should have. The instance is the actual object that gets created using that blueprint. So in this case, Cricketer is the constructor, and player1 and player2 are instances. Each instance has its own data like name and role, but they can share methods through the prototype.</p>
<h2>How this behaves</h2>
<p>When we use new, this refers to the newly created object every single time. That is why even if the same constructor and same methods are used, the output can be different because the data inside each object is different.</p>
<pre><code class="language-javascript">const player1 = new Cricketer("Virat Kohli", "Batter");
const player2 = new Cricketer("Bumrah", "Bowler");

player1.introduce();
player2.introduce();
</code></pre>
<p>Even though both are using the same introduce method, this points to player1 in the first call and player2 in the second call. So the values of name and role change accordingly, which results in different outputs.</p>
<h2>Constructor vs factory function</h2>
<p>There is another way of creating objects which is factory functions, and it is useful to understand the difference between both approaches because both are used in real codebases.</p>
<pre><code class="language-javascript">function User(name) {
  this.name = name;
}

const u1 = new User("A");
</code></pre>
<pre><code class="language-javascript">function createUser(name) {
  return {
    name: name
  };
}

const u2 = createUser("A");
</code></pre>
<p>In constructor functions, the new keyword handles object creation and binding of this automatically, whereas in factory functions we manually create and return the object. Both achieve similar outcomes but the internal approach is different.</p>
<h2>Classes are just a wrapper over this</h2>
<p>You must have come across classes in JavaScript, and they might look like something very different at first, but internally they are just a cleaner syntax over constructor functions and prototype logic. They do not introduce a new system, they just make the same thing easier to write and read.</p>
<pre><code class="language-javascript">class Cricketer {
  constructor(name, role) {
    this.name = name;
    this.role = role;
  }

  introduce() {
    console.log("Hi, I am " + this.name + " and I am a " + this.role);
  }
}

const player1 = new Cricketer("Virat Kohli", "Batter");
</code></pre>
<p>Internally, this still uses prototypes. Also, type of class is function, which shows that classes are just syntactic sugar over the existing system.</p>
<h2>Instances created from constructors</h2>
<p>When we use constructor functions with new, a new instance of the object is created every time. Each instance is independent in terms of data but can share behavior through the prototype.</p>
<pre><code class="language-javascript">const player1 = new Cricketer("Virat Kohli", "Batter");
const player2 = new Cricketer("Bumrah", "Bowler");
</code></pre>
<p>Both of these are different instances, and even though they are created from the same constructor, they do not interfere with each other’s data.</p>
<pre><code class="language-javascript">player1.introduce();
player2.introduce();
</code></pre>
<p>This is why calling methods on each instance produces different outputs, because this refers to the respective object each time.</p>
<h2>Final clarity</h2>
<p>The main idea is that the new keyword creates a new object, links that object to the constructor’s prototype, sets this to that object, and then returns it. Because of prototype linking, the object can access shared methods and properties, which is how inheritance is achieved here. At the same time, each instance remains independent in terms of its own data, which is why this behaves differently for each object created using the same constructor.</p>
]]></content:encoded></item></channel></rss>