<?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[Satpalsinh Rana]]></title><description><![CDATA[I am a software engineer who loves coding and Tea.]]></description><link>https://blogs.satpal.cloud</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1767287274080/f383494b-5b32-483c-b5b4-729b5b67cdd9.png</url><title>Satpalsinh Rana</title><link>https://blogs.satpal.cloud</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 07 Jun 2026 08:44:46 GMT</lastBuildDate><atom:link href="https://blogs.satpal.cloud/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Linux from my Eyes]]></title><description><![CDATA[The Filesystem That Doesn't Exist
Every Linux user knows /proc. But almost nobody knows what it actually is. It's not a filesystem. There are no files on any disk. Everything inside it is generated on]]></description><link>https://blogs.satpal.cloud/linux-from-my-eyes</link><guid isPermaLink="true">https://blogs.satpal.cloud/linux-from-my-eyes</guid><category><![CDATA[Linux]]></category><category><![CDATA[ChaiCode]]></category><dc:creator><![CDATA[Satpalsinh Rana]]></dc:creator><pubDate>Sun, 10 May 2026 12:09:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/191298f2-2398-4469-90e9-db59bb7a2805.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>The Filesystem That Doesn't Exist</h2>
<p>Every Linux user knows <code>/proc</code>. But almost nobody knows what it actually is. It's not a filesystem. There are no files on any disk. Everything inside it is generated on the fly by the kernel the moment you read it. It's theater a stage where the kernel performs its internal state for you, formatted as files.</p>
<p>This matters because it means reading <code>/proc/meminfo</code> is not like reading a log file. It is the act of asking the kernel a live question. The answer is constructed at the exact moment your <code>cat</code> command touches the file descriptor.</p>
<p>Imagine you walk into a library. You see thousands of books on the shelves. Normally, you’d pick one up, and the words inside would be printed in ink, unchanging since the day the book was made. That is a Standard Filesystem (like your hard drive).</p>
<p>But Linux has a ghost library called <code>/proc</code>. When you open a book in <code>/proc</code>, the pages are blank until your eyes touch the paper. The moment you look, a librarian (the Kernel) sprints behind the page and scribbles down exactly what is happening in the building at that microsecond. When you close the book, the ink vanishes.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/53fad349-e5ac-4704-bcfe-531b802a2065.png" alt="" style="display:block;margin:0 auto" />

<p>Notice the sizes: every file is <strong>0 bytes</strong>. That's the tell. Real files have sizes. These are kernel function pointers dressed as files. <code>/proc/self</code> is particularly mind-bending it's a symlink that points to the PID of whoever reads it. Every process that reads <code>/proc/self</code> sees itself. It's a mirror.</p>
<h2>Your Process Is a Directory</h2>
<p>Every running process gets its own directory in <code>/proc/[PID]/</code>. Inside that directory is a complete portrait of the process its open files, its memory map, its environment variables, its current working directory, what executable it is. This is not metadata. This is the process, seen from the outside.</p>
<h3><strong>What we found in PID 1</strong></h3>
<p>PID 1 is the init process the ancestor of all other processes. In a traditional Linux system, this is <code>systemd</code> or <code>init</code>. Here, it revealed something different:</p>
<h3>Command</h3>
<ul>
<li><p><code>/proc/1/</code>: This is the directory for the <strong>Init process</strong>, the mother of all processes. It is the first thing the kernel starts after booting.</p>
</li>
<li><p><code>cmdline</code>: This "file" contains the exact command used to start that process.</p>
</li>
<li><p><code>tr '\0' ' '</code>: Kernel files in <code>/proc</code> often use "null bytes" (<code>\0</code>) to separate arguments. This part of your command simply replaces those invisible separators with spaces so you can read them.</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/36cfb1bc-aa96-4521-b48f-df9dcea5e4da.png" alt="" style="display:block;margin:0 auto" />

<p>The output <code>/usr/lib/systemd/systemd</code> tells us that our system is managed by systemd.</p>
<p>In the illusion of the filesystem, this file exists to tell you exactly how the system was brought to life. The <code>--deserialize=79</code> flag is a piece of internal state a memory systemd kept of its previous self if it was re-executed without a full reboot.</p>
<h2>Network Knobs Hidden in /proc/sys/net</h2>
<p>Sysadmins tune Linux networking by writing numbers to files. Security hardening, performance tuning, DDoS mitigation all of it lives in /proc/sys/net/ipv4/ and friends. Most documentation tells you what to set. Almost none explains what you can read to understand the system's current posture.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/f0225c5f-3d8c-4163-a409-f7a50bfadcee.png" alt="" style="display:block;margin:0 auto" />

<h2>Everything is a File in Linux</h2>
<p>You're running a Node.js or Python server and under load it crashes with <code>EMFILE: too many open files</code>. This is one of the most common errors developers hit and one of the least understood. Here's the full picture.</p>
<p>Every open file, socket, pipe, or database connection consumes a <strong>file descriptor</strong> (FD). Linux enforces limits on how many a process can hold at once. There are two limits stacked on top of each other:</p>
<table>
<thead>
<tr>
<th><strong>Limit</strong></th>
<th><strong>Where it lives</strong></th>
<th><strong>Default</strong></th>
<th><strong>Scope</strong></th>
</tr>
</thead>
<tbody><tr>
<td>Soft limit</td>
<td><code>ulimit -n</code></td>
<td>1,024</td>
<td>Per process — the active ceiling. Can be raised to hard limit by user.</td>
</tr>
<tr>
<td>Hard limit</td>
<td><code>ulimit -Hn</code></td>
<td>4,096</td>
<td>Per process — the ceiling on the soft limit. Only root can raise.</td>
</tr>
<tr>
<td>System limit</td>
<td><code>/proc/sys/fs/file-max</code></td>
<td>~400,000</td>
<td>Entire OS — total FDs across all processes combined.</td>
</tr>
</tbody></table>
<p>The default soft limit of <strong>1,024</strong>. A modern web server handling 500 concurrent connections is already using half its budget just for sockets, before counting open config files, logs, and library handles.</p>
<h2></h2>
<p><strong>Address Already in Use</strong></p>
<p>You start your dev server and get <code>EADDRINUSE: address already in use :::3000</code>. Something is already listening on that port. Here's how to find and handle it.  </p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/526ecc23-1d54-4516-a3f0-5a0de38d065c.png" alt="" style="display:block;margin:0 auto" />

<p>Sometimes there's no process on the port but you still can't bind. This happens because the port is in <strong>TIME_WAIT</strong> state the kernel is holding it for 60 seconds after a recent connection closed, to ensure stale packets don't confuse a new connection.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/4c12f0fe-69be-4d12-87c4-c91193a953c4.png" alt="" style="display:block;margin:0 auto" />

<h2><strong>Zombie Processes</strong></h2>
<p>A zombie process is not a running process. It's a <strong>dead process whose exit code hasn't been collected yet</strong>. The kernel keeps a tiny tombstone entry in the process table until the parent calls <code>wait()</code> to read the exit status. Until then: zombie.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/a4f45c2b-31ef-4db6-826d-7bba11284c09.png" alt="" style="display:block;margin:0 auto" />

<table>
<thead>
<tr>
<th><strong>Scenario</strong></th>
<th><strong>Why zombies appear</strong></th>
<th><strong>Fix</strong></th>
</tr>
</thead>
<tbody><tr>
<td>Python <code>subprocess</code></td>
<td>You call <code>Popen()</code> but never call <code>.wait()</code> or <code>.communicate()</code></td>
<td>Always call <code>proc.wait()</code> or use <a href="http://subprocess.run"><code>subprocess.run</code></a><code>()</code></td>
</tr>
<tr>
<td>Node.js <code>child_process</code></td>
<td>Spawned process exits but <code>'exit'</code> event never handled</td>
<td>Listen to the <code>'exit'</code> or <code>'close'</code> event</td>
</tr>
<tr>
<td>Docker containers</td>
<td>Your app is PID 1 and spawns children without a proper init</td>
<td>Use <code>--init</code> flag or <code>tini</code> as PID 1</td>
</tr>
<tr>
<td>Shell scripts</td>
<td>Background jobs <code>&amp;</code> whose parent script exits without <code>wait</code></td>
<td>Call <code>wait</code> at end of script or use <code>wait $!</code> per job</td>
</tr>
</tbody></table>
<h2><code>/etc/hosts</code></h2>
<p><code>/etc/hosts</code> is checked <em>before</em> DNS. This is defined in <code>/etc/nsswitch.conf</code> as <code>hosts: files dns</code> "files" (hosts) first, "dns" second. This makes <code>/etc/hosts</code> an instant, zero-latency DNS override with no servers involved.</p>
<table>
<thead>
<tr>
<th><strong>Entry to add</strong></th>
<th><strong>What it does for you</strong></th>
</tr>
</thead>
<tbody><tr>
<td><code>127.0.0.1 myapp.local</code></td>
<td>Access your local dev server at <a href="http://myapp.local:3000"><code>http://myapp.local:3000</code></a> in any browser — useful when cookies or CORS require a real-looking hostname.</td>
</tr>
<tr>
<td><code>127.0.0.1 api.myapp.local</code></td>
<td>Fake a subdomain for your local API. No DNS server. No Nginx. Just edit hosts and curl works immediately.</td>
</tr>
<tr>
<td><code>0.0.0.0</code> <a href="http://ads.tracker.com"><code>ads.tracker.com</code></a></td>
<td>Block a domain entirely by routing it to 0.0.0.0 (not routable, fails fast). More effective than 127.0.0.1 because 127.0.0.1 might have something listening.</td>
</tr>
<tr>
<td><code>192.168.1.50 staging</code></td>
<td>Give your staging server a short name. Now you can <code>ssh staging</code>, <code>curl staging:8080</code>, etc.</td>
</tr>
<tr>
<td><code>127.0.0.1</code> <a href="http://prod-db.company.com"><code>prod-db.company.com</code></a></td>
<td>Intercept production DNS for testing. Point the production hostname to localhost temporarily. Useful for testing without modifying app configs.</td>
</tr>
</tbody></table>
<h2><strong>Quick Reference Cheatsheet</strong></h2>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/3b53bac8-3e39-4ae4-9fa1-171d1cb04081.png" alt="" style="display:block;margin:0 auto" />]]></content:encoded></item><item><title><![CDATA[JWT Authentication ]]></title><description><![CDATA[Why we need Authentication in our application
Imagine you walk into a private club. The bouncer doesn't just let you in because you look nice you need a membership card. In the digital world, Authenti]]></description><link>https://blogs.satpal.cloud/jwt-authentication</link><guid isPermaLink="true">https://blogs.satpal.cloud/jwt-authentication</guid><category><![CDATA[JWT]]></category><category><![CDATA[ChaiCode]]></category><category><![CDATA[Express]]></category><category><![CDATA[Node.js]]></category><dc:creator><![CDATA[Satpalsinh Rana]]></dc:creator><pubDate>Sat, 09 May 2026 13:53:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/b3d08699-1d67-471b-b5e8-a80089e91786.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3>Why we need Authentication in our application</h3>
<p>Imagine you walk into a private club. The bouncer doesn't just let you in because you look nice you need a membership card. In the digital world, <strong>Authentication</strong> is that process it’s how a server verifies that you are who you say you are.</p>
<p>Without it, anyone could edit your profile, delete your data, or post on your behalf. We need a way to prove identity once, then stay "logged in" without having to type a password for every single button click.</p>
<h2>What is a JWT (JSON Web Token)?</h2>
<p>In the old days, servers kept a list of every logged-in user in their memory (Sessions). It was like a bouncer memorizing every face in the club. But if the club gets too big, the bouncer’s head explodes.</p>
<p><strong>JWT (JSON Web Token)</strong> is the modern, "stateless" solution. Instead of the server remembering you, it gives you a digital, tamper-proof ID card. You carry it, you show it, and the server just checks if the signature is valid. It doesn't need to check a database every single time.</p>
<h2>The Secret Handshake: Why Your App Needs Authentication</h2>
<p>Imagine you walk into a private club. The bouncer doesn't just let you in because you look nice; you need a membership card. In the digital world, <strong>Authentication</strong> is that process—it’s how a server verifies that you are who you say you are.</p>
<p>Without it, anyone could edit your profile, delete your data, or post on your behalf. We need a way to prove identity once, then stay "logged in" without having to type a password for every single button click.</p>
<hr />
<h2>What is a JWT (JSON Web Token)?</h2>
<p>In the old days, servers kept a list of every logged-in user in their memory (Sessions). It was like a bouncer memorizing every face in the club. But if the club gets too big, the bouncer’s head explodes.</p>
<p><strong>JWT (JSON Web Token)</strong> is the modern, "stateless" solution. Instead of the server remembering you, it gives you a digital, tamper-proof ID card. You carry it, you show it, and the server just checks if the signature is valid. It doesn't need to check a database every single time.</p>
<h3>The Anatomy of a JWT</h3>
<p>A JWT looks like a long, messy string of gibberish separated by two dots. It has three distinct parts:</p>
<ol>
<li><p><strong>Header:</strong> Tells the server what kind of token this is and which hashing algorithm was used (usually HS256).</p>
</li>
<li><p><strong>Payload:</strong> The important part of the token. It contains user data like <code>userId</code> or <code>username</code>.<br />Don’t put passwords or secrets here; anyone can decode this part easily!</p>
</li>
<li><p><strong>Signature:</strong> This is the secret sauce. The server takes the Header and Payload, mixes them with a <strong>Secret Key</strong> known only to the server, and creates a unique hash. If even one character in the payload changes, the signature won't match anymore.</p>
</li>
</ol>
<h2>JWT Lifecycle</h2>
<h3>The Login Flow</h3>
<p>When a user logs in, the magic happens in these steps:</p>
<ol>
<li><p>Request: The user sends their username and password to the server.</p>
</li>
<li><p>Validation: The server checks the database. If the credentials are correct, the server creates a JWT using its private SECRET_KEY.</p>
</li>
<li><p>Delivery: The server sends that JWT back to the browser.</p>
</li>
</ol>
<h3>Sending the Token</h3>
<p>Once the browser has the token, it doesn't just sit there.</p>
<ol>
<li><p>For every "protected" request (like fetching your private messages), the browser sends the token in the Authorization Header: Authorization: Bearer &lt;your_token_here&gt;</p>
</li>
<li><p>Protecting Routes On the Node.js side, we use Middleware to protect specific routes.</p>
</li>
<li><p>The server intercepts the request.</p>
</li>
<li><p>It grabs the token from the header.</p>
</li>
<li><p>It verifies the signature using the SECRET_KEY.</p>
</li>
<li><p>If valid: The request proceeds to the controller.</p>
</li>
<li><p>If invalid: The server sends back a "401 Unauthorized" error.</p>
</li>
</ol>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/0457bfda-7799-4bd7-9808-05fa97874fdd.png" alt="JWT flow" style="display:block;margin:0 auto" />

<h2>Things as dev we should know</h2>
<ul>
<li><p><strong>JWTs are not "Encrypted":</strong> They are <strong>Encoded</strong>. Anyone can paste a JWT into <a href="http://jwt.io"><code>jwt.io</code></a> and read your payload. Never put sensitive data like credit card numbers or passwords inside a JWT.</p>
</li>
<li><p><strong>The "Stateless" Trap:</strong> Since the server doesn't "track" the token, you can't easily revoke it. If a user’s token is stolen, they are logged in until it expires. This is why <strong>Expiration Times</strong> (<code>exp</code>) are mandatory.</p>
</li>
<li><p><strong>Local Storage vs. Cookies:</strong> Storing tokens in <code>localStorage</code> makes you vulnerable to XSS (Cross-Site Scripting). For better security, many pros use <strong>HttpOnly Cookies</strong>, which JavaScript cannot touch.</p>
</li>
<li><p><strong>Secret Key Safety:</strong> If your <code>SECRET_KEY</code> leaks, your entire security system is compromised. Use environment variables and never, ever hardcode it into your GitHub repo.</p>
</li>
</ul>
<p><img src="align=%22center%22" alt="" /></p>
]]></content:encoded></item><item><title><![CDATA[Storing Uploaded Files and Serving Them in Express]]></title><description><![CDATA[As we have seen in previous article how to upload file using express and multer. Uploading a file is just the first half of the story. The other half where it lives and how you retrieve it.
Where Uplo]]></description><link>https://blogs.satpal.cloud/storing-and-serving-files</link><guid isPermaLink="true">https://blogs.satpal.cloud/storing-and-serving-files</guid><category><![CDATA[Node.js]]></category><category><![CDATA[Express]]></category><category><![CDATA[ChaiCode]]></category><dc:creator><![CDATA[Satpalsinh Rana]]></dc:creator><pubDate>Sat, 09 May 2026 13:42:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/8dbdc54b-2751-4da8-b861-25f09e218cff.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As we have seen in previous article how to upload file using express and multer. Uploading a file is just the first half of the story. The other half where it lives and how you retrieve it.</p>
<h2>Where Uploaded Files Actually Live</h2>
<p>When Multer processes a file, it writes it to a location on your server's filesystem. Exactly where depends on how you configured your storage. With the simple <code>dest</code> option, all files go into one flat folder. With <code>diskStorage</code>, you control every part of the path.</p>
<p>By default, that folder is relative to wherever your <code>node</code> process is started usually the project root. So <code>dest: 'uploads/'</code> means the files end up at <code>your-project/uploads/</code>. They live on disk like any other files, readable by any process with access to that directory.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/55f12657-331b-4094-b623-64f9019cb452.png" alt="" style="display:block;margin:0 auto" />

<blockquote>
<p>Use subfolders within <code>uploads/</code> to separate different file types — avatars, documents, product images. It keeps the directory manageable and makes it easier to apply different policies (expiry, access control) per category.</p>
</blockquote>
<h2>Local Storage vs. External Storage</h2>
<p>When you first build file upload functionality, storing files on the same server your application runs on <strong>local disk storage</strong> is the natural choice. It's simple, fast, and requires no third-party services. For development and low-traffic applications, it works perfectly well.</p>
<p>At scale, though, local disk has a few fundamental problems: disk space is finite, files don't survive server replacements or container restarts, and if you run multiple instances of your server behind a load balancer, only the instance that received the upload has the file. External storage services like S3, Cloudinary, or Google Cloud Storage exists to solve these problems.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/87e9be09-2bd1-4d82-969d-32941c2d9d84.png" alt="" style="display:block;margin:0 auto" />

<p>This article focuses on local disk — the right place to start. External storage integrations (AWS S3, etc.) follow the same conceptual model but involve additional SDK configuration. Once you understand local storage, the leap to cloud storage is mostly configuration, not new concepts.</p>
<h2>Serving Static Files in Express</h2>
<p>Express ships with a built-in middleware called <code>express.static()</code>. When you mount it, Express looks in the specified folder for a matching file whenever a GET request comes in. If a file is found, Express serves it directly without touching any of your route handlers. If it isn't found, the request falls through to whatever comes next in your middleware chain.</p>
<pre><code class="language-javascript">const express = require('express');
const path    = require('path');
const app     = express();

// Serve files from the uploads/ directory
// under the URL prefix /uploads
app.use(
  '/uploads',
  express.static(path.join(__dirname, 'uploads'))
);

// Now a file at: uploads/avatars/user-001.jpg
// Is served at:  GET /uploads/avatars/user-001.jpg
</code></pre>
<p>Using <code>path.join(__dirname, 'uploads')</code> instead of a relative string is worth noting. Relative paths are resolved from wherever the <code>node</code> process was launched, which can cause confusing "file not found" errors if you start your server from a different directory. <code>__dirname</code> is always the directory of the current file reliable regardless of where you invoke node.</p>
<blockquote>
<p><code>express.static()</code> <em>is essentially a tiny file server baked into your Express app. It handles caching headers, ETags, range requests, and content-type detection things you'd spend hours implementing yourself.</em></p>
</blockquote>
<h3>Controlling the URL prefix</h3>
<p>The first argument to <code>app.use()</code> sets the URL prefix. You can use any path you like it doesn't have to match the folder name. A user never needs to know your server's folder structure:</p>
<pre><code class="language-javascript">// Folder: uploads/
// Public URL prefix: /media
app.use('/media', express.static('uploads'));

// File on disk: uploads/photo.jpg
// Accessed via: GET /media/photo.jpg  
</code></pre>
<h2>Accessing Uploaded Files via URL</h2>
<p>The most common pattern is to return the file's URL immediately after upload, so the client can display or link to it right away. Your route handler should construct the URL from the saved filename:</p>
<pre><code class="language-javascript">app.post('/upload/avatar', upload.single('avatar'), (req, res) =&gt; {
  if (!req.file) {
    return res.status(400).json({ error: 'No file received' });
  }

  // Build a public-facing URL from the saved filename
  const fileUrl = `\({req.protocol}://\){req.get('host')}/uploads/${req.file.filename}`;

  // Typically you'd save fileUrl to a database here
  res.status(201).json({
    message: 'Upload successful',
    url:     fileUrl,
  });
});
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/36541420-34d0-41a6-a4d4-8e83fadb8dfc.png" alt="" style="display:block;margin:0 auto" />

<h2>Security Considerations for Uploads</h2>
<p>File uploads are one of the most common attack vectors in web applications. A form that accepts files is essentially an invitation for users to send whatever they want to your server. The defaults are not safe you have to explicitly lock things down.</p>
<h3>The non-negotiables</h3>
<ul>
<li><p><strong>Always set a file size limit.</strong> Without <code>limits.fileSize</code>, a user can upload a multi-gigabyte file and crash your server.</p>
</li>
<li><p><strong>Validate the file type server-side.</strong> Checking <code>file.mimetype</code> is a minimum. For sensitive use cases, inspect magic bytes with a library like <code>file-type</code>.</p>
</li>
<li><p><strong>Never use the original filename.</strong> A user could send <code>../../../etc/passwd</code> as a filename. Always generate your own — Multer's random hash or your own UUID.</p>
</li>
<li><p><strong>Store uploads outside the web root.</strong> If your uploads folder is outside <code>public/</code>, it can't be served accidentally. Only expose files you explicitly serve via static middleware.</p>
</li>
<li><p><strong>Never execute uploaded files.</strong> Even if you're expecting a script file, never run it. Uploaded files should be treated as data — read, stored, downloaded. Never executed.</p>
</li>
<li><p><strong>Consider image resizing/re-encoding.</strong> A malicious PNG can embed harmful data in metadata or exploit decoder vulnerabilities. Re-encoding images with a library like <code>sharp</code> strips unknown data.</p>
</li>
</ul>
<h3>Error handling for rejected uploads</h3>
<p>When Multer rejects a file due to file size, bad type, or too many files — it passes an error to the next middleware. You need to catch this explicitly, otherwise Express will respond with a generic 500:</p>
<pre><code class="language-javascript">app.post('/upload', (req, res, next) =&gt; {
  upload.single('image')(req, res, (err) =&gt; {
    if (err instanceof multer.MulterError) {
      // Multer-specific errors (LIMIT_FILE_SIZE, etc.)
      if (err.code === 'LIMIT_FILE_SIZE') {
        return res.status(413).json({ error: 'File too large. Max 5 MB.' });
      }
      return res.status(400).json({ error: err.message });
    }
    if (err) {
      // fileFilter or other custom errors
      return res.status(400).json({ error: err.message });
    }

    // No error — proceed normally
    handleUpload(req, res);
  });
});

function handleUpload(req, res) {
  if (!req.file) return res.status(400).json({ error: 'No file' });
  res.json({ url: `/uploads/${req.file.filename}` });
}
</code></pre>
<h2>Complete Example: Upload, Store, Serve</h2>
<p>Here is a fully working minimal server that combines storage configuration, static file serving, file type filtering, size limits, and proper error handling:</p>
<pre><code class="language-javascript">const express = require('express');
const multer  = require('multer');
const path    = require('path');
const fs      = require('fs');

const app        = express();
const UPLOAD_DIR = path.join(__dirname, 'uploads');

// Ensure the uploads folder exists
fs.mkdirSync(UPLOAD_DIR, { recursive: true });

// Storage 
const storage = multer.diskStorage({
  destination: (req, file, cb) =&gt; cb(null, UPLOAD_DIR),
  filename:    (req, file, cb) =&gt; {
    const ext    = path.extname(file.originalname).toLowerCase();
    const unique = `${Date.now()}-` + Math.random().toString(36).slice(2);
    cb(null, unique + ext);
  },
});

// Multer instance 
const upload = multer({
  storage,
  limits:     { fileSize: 5_000_000 },
  fileFilter: (req, file, cb) =&gt; {
    const ok = ['image/jpeg', 'image/png', 'image/webp'];
    cb(ok.includes(file.mimetype) ? null : new Error('Images only'), ok.includes(file.mimetype));
  },
});

// Static serving 
app.use('/uploads', express.static(UPLOAD_DIR));

// Upload route (with error handling) 
app.post('/upload', (req, res) =&gt; {
  upload.single('image')(req, res, (err) =&gt; {
    if (err) {
      const status = err.code === 'LIMIT_FILE_SIZE' ? 413 : 400;
      return res.status(status).json({ error: err.message });
    }
    if (!req.file) {
      return res.status(400).json({ error: 'No file provided' });
    }

    const fileUrl = `/uploads/${req.file.filename}`;
    res.status(201).json({ url: fileUrl });
  });
});

app.listen(3000, () =&gt; console.log('Server on :3000'));
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Handling File Uploads in Express with Multer]]></title><description><![CDATA[Why File Uploads Need Middleware
When you submit a plain HTML form name, email, that sort of thing the browser encodes everything as application/x-www-form-urlencoded. It's a simple key=value string, ]]></description><link>https://blogs.satpal.cloud/express-with-multer</link><guid isPermaLink="true">https://blogs.satpal.cloud/express-with-multer</guid><category><![CDATA[multer]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[Express]]></category><category><![CDATA[ChaiCode]]></category><dc:creator><![CDATA[Satpalsinh Rana]]></dc:creator><pubDate>Sat, 09 May 2026 13:33:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/e52baf60-10e9-485f-ac74-43dbf35fd023.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2><strong>Why File Uploads Need Middleware</strong></h2>
<p>When you submit a plain HTML form name, email, that sort of thing the browser encodes everything as <code>application/x-www-form-urlencoded</code>. It's a simple key=value string, and Express's built-in body parser handles it without complaint.</p>
<p>But the moment a <code>&lt;input type="file"&gt;</code> enters the picture, the rules change. The browser switches to a completely different encoding: <strong>multipart/form-data</strong>. Instead of a flat string, it sends a binary stream divided into labeled sections called "parts" one for each field, one for each file. Each part has headers, a boundary marker, and its own raw content.</p>
<blockquote>
<p><em>Think of multipart/form-data like a series of envelopes inside one package. Each envelope is a separate field — some contain plain text, others contain binary file data.</em></p>
</blockquote>
<p>Express's default body parsers don't know how to open those envelopes. They'll parse JSON, they'll parse URL-encoded text, but multipart? They leave it alone. That's why you need dedicated middleware something that can read the binary stream, separate the parts, and hand them to your route handler in a usable shape.</p>
<blockquote>
<p><strong>Why not use body-parser?</strong><br />The popular <code>body-parser</code> package explicitly does not support multipart bodies. Its README says so. This is by design multipart parsing is complex enough to warrant its own focused library.</p>
</blockquote>
<h2><strong>What Multer Is</strong></h2>
<p><strong>Multer</strong> is a Node.js middleware built specifically for handling <code>multipart/form-data</code>. It sits between the incoming request and your route handler, reads the binary stream, separates files from text fields, and attaches everything neatly to <code>req.file</code> or <code>req.files</code>.</p>
<p>Multer is built on top of <strong>busboy</strong>, a fast streaming multipart parser. It's the most widely used file upload middleware in the Express ecosystem, and for good reason it handles the messy parts so you don't have to.</p>
<p>Install it alongside Express:</p>
<pre><code class="language-shell">npm install express multer
</code></pre>
<p>Multer's job is straightforward: intercept the request before your route handler runs, extract all the file and field data, save files to wherever you've configured, and populate <code>req.body</code> (for text fields) and <code>req.file</code> / <code>req.files</code> (for uploaded files).</p>
<p><strong>The Upload Lifecycle</strong></p>
<p>Before writing any code, it helps to see the full picture of what happens when a file travels from a browser to your server:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/b199e68f-b3b4-474a-bdbe-bcffd49bc288.png" alt="" style="display:block;margin:0 auto" />

<p>Three steps, every time: the browser sends the multipart stream, Multer intercepts and processes it, and your handler receives clean, ready-to-use file data.</p>
<h2><strong>Handling a Single File Upload</strong></h2>
<p>Let's start with the most common case a user uploading one file. The HTML side is just a standard form with <code>enctype="multipart/form-data"</code>. Without that attribute, the file never makes it to the server.</p>
<p>Create a UI</p>
<pre><code class="language-html">&lt;form action="/upload" method="POST" enctype="multipart/form-data"&gt;
  &lt;input type="file" name="avatar" /&gt;
  &lt;button type="submit"&gt;Upload&lt;/button&gt;
&lt;/form&gt;
</code></pre>
<p>On the server, Multer's <code>.single(fieldName)</code> method returns middleware that looks for one file in the named field:</p>
<pre><code class="language-javascript">const express = require('express');
const multer  = require('multer');

const app    = express();
const upload = multer({ dest: 'uploads/' });

// .single('avatar') → look for a field named "avatar"
app.post('/upload', upload.single('avatar'), (req, res) =&gt; {

  // req.file contains the uploaded file metadata
  // req.body contains any other text fields
  if (!req.file) {
    return res.status(400).json({ error: 'No file uploaded' });
  }

  res.json({
    message:      'Upload successful',
    filename:     req.file.filename,
    originalName: req.file.originalname,
    size:         req.file.size,
    mimetype:     req.file.mimetype,
  });
});

app.listen(3000);
</code></pre>
<p>After Multer runs, <code>req.file</code> is an object with everything you need to know about the uploaded file. The most useful properties: req.file</p>
<pre><code class="language-plaintext">{
  fieldname:   'avatar',         // HTML field name
  originalname:'profile-pic.jpg',  // filename from user's machine
  encoding:    '7bit',
  mimetype:    'image/jpeg',       // detected content type
  destination: 'uploads/',         // folder where file was saved
  filename:    'a3f9c1b2d4e8...',  // generated unique name (no ext)
  path:        'uploads/a3f9c1...',// full path on disk
  size:        82034               // bytes
}
</code></pre>
<blockquote>
<p>When using <code>dest</code> shorthand, Multer saves files <em>without their original extension</em>. The filename is a random hash. You'll need to rename it or use <code>diskStorage</code> if you want to preserve extensions — covered in the Storage section below.</p>
</blockquote>
<h2><strong>Handling Multiple File Uploads</strong></h2>
<p>Two situations arise with multiple files. Either the user uploads several files through <em>one</em> input field, or you have multiple fields each accepting their own files. Multer has a method for each.</p>
<h3><strong>Multiple files from a single field</strong></h3>
<p>Use <code>.array(fieldName, maxCount)</code>. The second argument is optional but highly recommended it caps how many files can arrive in one request:</p>
<pre><code class="language-javascript">app.post('/upload-many', upload.array('photos', 10), (req, res) =&gt; {

  // req.files is an array of file objects
  const filenames = req.files.map(f =&gt; f.filename);
  res.json({ uploaded: filenames });

});
</code></pre>
<h3><strong>Files from multiple fields</strong></h3>
<p>Use <code>.fields()</code> when each field has a distinct name. Pass an array of field descriptors:</p>
<pre><code class="language-javascript">const cpUpload = upload.fields([
  { name: 'avatar',   maxCount: 1  },
  { name: 'portfolio', maxCount: 5  },
]);

app.post('/profile', cpUpload, (req, res) =&gt; {

  // req.files is now an object, keyed by field name
  const avatar    = req.files['avatar'][0];    // one file
  const portfolio = req.files['portfolio'];    // array of files

  res.json({ avatarName: avatar.filename });
});
</code></pre>
<h2><strong>Storage Configuration Basics</strong></h2>
<p>The <code>dest</code> shorthand is fine for quick experiments, but production code usually needs more control. Multer's <code>diskStorage</code> engine gives you two configuration hooks: where to put the file, and what to name it.</p>
<pre><code class="language-javascript">const path   = require('path');
const multer = require('multer');

const storage = multer.diskStorage({

  // 1. Where should the file be saved?
  destination(req, file, cb) {
    cb(null, 'uploads/');  // first arg is error (null = no error)
  },

  // 2. What should the file be called?
  filename(req, file, cb) {
    const ext      = path.extname(file.originalname);
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
    cb(null, file.fieldname + '-' + uniqueSuffix + ext);
    // Result: "avatar-1718023456789-382910483.jpg"
  },

});

const upload = multer({ storage });
</code></pre>
<p>Both <code>destination</code> and <code>filename</code> follow the same node-style callback pattern: the first argument to <code>cb</code> is an error (pass <code>null</code> to proceed), and the second is your value. This pattern lets you run async logic like checking a database before deciding where a file should land.</p>
<h2><strong>File Type Filtering</strong></h2>
<p>You don't want users uploading executable files when you're expecting images. Multer lets you filter incoming files with a <code>fileFilter</code> function. If the filter rejects a file, the request continues without it — or you can throw an error:</p>
<pre><code class="language-javascript">function imageFilter(req, file, cb) {
  const allowed = ['image/jpeg', 'image/png', 'image/webp'];

  if (allowed.includes(file.mimetype)) {
    cb(null, true);   // accept the file
  } else {
    cb(new Error('Only JPEG, PNG, and WebP images are allowed'));
  }
}

const upload = multer({
  storage,
  fileFilter: imageFilter,
  limits: { fileSize: 5 * 1024 * 1024 }  // 5 MB cap
});
</code></pre>
<h2><strong>Serving Uploaded Files</strong></h2>
<p>Saving files is half the job. Once they're on disk, you need users to be able to retrieve them. Express's built-in <code>express.static()</code> middleware makes this trivially easy:</p>
<pre><code class="language-javascript">// Serve everything in the uploads/ folder under the /uploads URL path
app.use('/uploads', express.static('uploads'));

// A file saved at uploads/avatar-1718023456.jpg
// is now available at: http://localhost:3000/uploads/avatar-1718023456.jpg
</code></pre>
<p>That one line turns your upload folder into a file server. Any file sitting in <code>uploads/</code> becomes publicly accessible via its filename in the URL.</p>
<h3><strong>Key Takeaways</strong></h3>
<ol>
<li><p>HTML forms must use<code>enctype="multipart/form-data"</code>— without it, no file data is sent.</p>
</li>
<li><p>Multer interposes itself in the middleware chain, reading the stream before your handler runs.</p>
</li>
<li><p>Use<code>.single()</code>,<code>.array()</code>, or<code>.fields()</code>depending on your form shape.</p>
</li>
<li><p><code>diskStorage</code>gives full control over folder and filename; use it in production.</p>
</li>
<li><p>Always limit file size and filter by type to prevent abuse.</p>
</li>
<li><p><code>express.static()</code></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Sessions vs JWT vs Cookies]]></title><description><![CDATA[You've seen the Stack Overflow answers. You've skimmed the Medium posts. You know the drill sessions store state on the server, JWTs are stateless, cookies are just the transport. Got it.
But then you]]></description><link>https://blogs.satpal.cloud/sessions-vs-jwt-vs-cookies</link><guid isPermaLink="true">https://blogs.satpal.cloud/sessions-vs-jwt-vs-cookies</guid><dc:creator><![CDATA[Satpalsinh Rana]]></dc:creator><pubDate>Sat, 09 May 2026 13:08:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/7c359488-2ea5-40c8-95e3-2a68a854e5d7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You've seen the Stack Overflow answers. You've skimmed the Medium posts. You know the drill <em>sessions store state on the server, JWTs are stateless, cookies are just the transport.</em> Got it.</p>
<p>But then you actually build auth and a weird bug shows up. A logged-out user still gets in. Your JWT is 8 kilobytes. Your "stateless" microservices are calling a central database on every request. Something is off.</p>
<p>This article is about those moments. The things tutorials skip. Let's go from the foundations up, but stop at the places where the real decisions live.</p>
<h2><strong>Cookies: Just a Box in the Truck</strong></h2>
<p>Here's the misconception that causes the most confusion: <strong>a cookie is not an authentication strategy.</strong> It's a storage mechanism a key-value pair the browser saves and automatically sends back with every request to the same domain.</p>
<p>That's it. The browser does the sending for you. You don't write any fetch logic to attach cookies to requests. This is both a convenience and the source of CSRF attacks.</p>
<blockquote>
<p>Cookies predate modern JavaScript. They were designed for a world without <code>fetch()</code>. The browser's automatic attachment behavior is a legacy of that era — and it's exactly what makes them dangerous if you don't set the right flags.</p>
</blockquote>
<h3><strong>The Three flags you must set</strong></h3>
<p>Every developer knows cookies exist. Few consistently set all three of these on production auth cookies:</p>
<ul>
<li><p><code>HttpOnly</code>Prevents JavaScript from reading the cookie. This is the single most effective mitigation against XSS stealing your session token. If you can access your auth cookie via <code>document.cookie</code>, you've already lost.</p>
</li>
<li><p><code>Secure</code>Only sends the cookie over HTTPS. Without this, your token travels in cleartext. You'd be surprised how many staging environments skip this and then wonder why tokens leak.</p>
</li>
<li><p><code>SameSite=Strict</code> <strong>or</strong> <code>Lax</code>Controls cross-site sending. <code>Strict</code> is safest — the cookie won't go with any cross-origin request. <code>Lax</code> allows top-level navigations (clicking a link). The default used to be <code>None</code>, which is a CSRF nightmare. Modern browsers default to <code>Lax</code> now, but don't rely on that.</p>
</li>
</ul>
<blockquote>
<p>Storing a JWT inside <code>localStorage</code> gives it zero of the protections above. Any XSS vulnerability on your page can read it, send it anywhere, and impersonate your user indefinitely — because JWTs don't expire until their <code>exp</code> claim says so.</p>
</blockquote>
<h2><strong>Sessions: The Server Remembers You</strong></h2>
<p>Session-based authentication is the original approach. It works like a coat check at a restaurant. You hand over your coat (credentials), they give you a numbered ticket (session ID), and later you return the ticket to get the coat back.</p>
<p>The server stores the actual session data user ID, roles, cart contents, whatever in memory or a database. The client only holds the ticket. The ticket itself is meaningless without the server's ledger.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/2714511f-20bd-449a-af70-a2d385b57ec6.png" alt="" style="display:block;margin:0 auto" />

  
<p>The critical thing to understand: the session ID that lives in the cookie is <strong>opaque</strong>. It's a random string. It carries zero information on its own. All the meaning lives server-side.</p>
<blockquote>
<p><strong>The "sessions don't scale" myth.</strong> You'll hear that sessions are stateful and therefore don't scale horizontally. This was true when sessions lived in server memory. Move session storage to Redis and suddenly you have a distributed, in-memory session store that handles hundreds of thousands of concurrent users. The real cost is the round-trip to Redis — about 0.5–2ms on a co-located instance. That's a completely acceptable trade-off for most applications.</p>
</blockquote>
<h2><strong>JWT: The Server Trusts Your ID Card</strong></h2>
<p>JSON Web Tokens take a different philosophy. Instead of storing state on the server, you <em>encode</em> state into a token and send it to the client. The server signs the token cryptographically, so when the client sends it back, the server can verify the signature without looking anything up.</p>
<p>A JWT has three parts separated by dots: <code>header.payload.signature</code>. Base64URL-encoded. The payload is where your user data lives.</p>
<blockquote>
<p><strong>The most common JWT misconception:</strong> JWT is <em>signed</em>, not <em>encrypted</em>. Anyone can decode the payload — just paste it into <a href="http://jwt.io">jwt.io</a>. Never put sensitive data (passwords, PII, API keys) in the payload. The signature only proves it wasn't tampered with; it doesn't hide the contents.</p>
</blockquote>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/5f08785d-5907-409d-a461-064951679894.png" alt="" style="display:block;margin:0 auto" />

<p>This "no database lookup" property is genuinely useful in microservice architectures where many services need to know who the user is. Pass the JWT and every service can independently verify it using the same public key.</p>
<h3><strong>What "stateless" actually costs you</strong></h3>
<p>Here's where most tutorials stop — but you shouldn't.</p>
<ul>
<li><p><strong>You can't revoke a JWT.</strong> If a user logs out, changes their password, or you ban them — the JWT is still valid until it expires. The server has no record of it to invalidate. Your options: short expiry times (5–15 minutes) with refresh tokens, or maintain a token blocklist — which is just a session store under a different name.</p>
</li>
<li><p><strong>Refresh tokens bring back state.</strong> The standard pattern is a short-lived access token + a long-lived refresh token. The refresh token lives in the database. So you now have server-side state again. You've solved one problem (DB lookup per request) while creating another (periodic DB calls to refresh). Know the trade-off you're making.</p>
</li>
<li><p><strong>Token size hits your header limits.</strong> A typical JWT with a few claims is 500–700 bytes. Add roles, permissions, and org context and you can easily hit 2–4KB. Some proxies and CDNs have header size limits. Every request carries this overhead. Compare that to a 32-byte session ID.</p>
</li>
<li><p><strong>Clock skew can expire tokens prematurely.</strong> JWTs use Unix timestamps for <code>iat</code>, <code>nbf</code>, and <code>exp</code>. If your servers aren't NTP-synced, a token signed on Server A might be rejected as expired or "not yet valid" by Server B. Most libraries include a small leeway (60s), but this bites teams with containerized environments that don't sync clocks properly.</p>
</li>
<li><p><strong>Algorithm confusion attacks are real.</strong> The JWT header specifies which algorithm was used to sign the token. An early class of vulnerabilities involved setting the algorithm to <code>none</code> and removing the signature — some libraries would accept this. Always explicitly specify which algorithms your library should accept. Never trust the header's algorithm claim blindly.</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/1f76a767-3753-4570-85e4-54e89724f0a1.png" alt="" style="display:block;margin:0 auto" />

<h2><strong>When to Use Each</strong></h2>
<p><em>"The best auth system is the one your team understands well enough to avoid shooting themselves in the foot."</em></p>
<h4>Reach for Sessions when</h4>
<ul>
<li><p>You need instant account revocation (banking, enterprise SaaS)</p>
</li>
<li><p>Your app is a single domain — no cross-subdomain auth needed</p>
</li>
<li><p>You change user roles frequently</p>
</li>
<li><p>You're a small team and want simple, proven auth</p>
</li>
<li><p>You have access to a shared cache (Redis) for your servers</p>
</li>
</ul>
<h4>Reach for JWT when</h4>
<ul>
<li><p>Multiple services need to verify identity independently</p>
</li>
<li><p>You have mobile clients or third-party API consumers</p>
</li>
<li><p>You're building an auth server (OAuth / OIDC)</p>
</li>
<li><p>Cross-domain or cross-subdomain auth is required</p>
</li>
<li><p>You can tolerate short windows of stale token data</p>
</li>
</ul>
<h2>Best Practices to follow while build Auth System</h2>
<h3><strong>JWT in a cookie is usually better than JWT in localStorage</strong></h3>
<p>The instinct when using JWTs is to store them in <code>localStorage</code> it's JavaScript-accessible, simple to use, and feels "modern." But <code>localStorage</code> is readable by any script on your page. One XSS vulnerability and your token is gone. Store JWT in a <code>HttpOnly</code> cookie and you get the best of both worlds: stateless verification on the server, and XSS-resistant storage on the client.</p>
<p>The trade-off is that cookies bring CSRF exposure back. Handle it with <code>SameSite=Strict</code> and you've solved that too. This combination JWT + HttpOnly cookie + SameSite is what most security-conscious teams actually use in production.</p>
<h3><strong>The "sub" claim should be an opaque ID, not an email</strong></h3>
<p>The <code>sub</code> (subject) claim in JWT is supposed to identify who the token is for. Beginners often put the user's email address here. The problem: emails change. If a user changes their email and you're using it as a key, you've got a mismatch. Use an internal UUID or integer ID that never changes.</p>
<h3><strong>Don't put sensitive data in the JWT payload</strong></h3>
<p>Again, because this cannot be said enough: <code>eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjQyLCJzc246IjEyMy00NS02Nzg5In0</code> is not encrypted. The middle section decodes to plain JSON. Never put SSNs, passwords, credit card tokens, or any PII in the payload. The signature proves authenticity; it doesn't provide confidentiality. If you need confidentiality, use JWE (JSON Web Encryption) but that's a separate spec and significantly more complex.</p>
<h3><strong>Set a sane expiry on sessions too</strong></h3>
<p>Developers obsess over JWT expiry but forget to set expiry on sessions. A session with no TTL in Redis (or no timeout in your session library) lives forever. A user who logged in three years ago and never explicitly logged out still has a valid session. Set both absolute expiry and idle timeout. Absolute: "this session is invalid after 30 days regardless." Idle: "this session is invalid if unused for 2 hours."</p>
<p>Authentication is one of those topics where the basics are well-documented, and the hard parts are learned through painful production incidents. The goal isn't to pick the "right" answer it's to pick the approach whose trade-offs your team understands completely.</p>
<p>Sessions give you control and simplicity. JWTs give you distribution and flexibility. Cookies give both a transport mechanism. None of them are magic. All of them have sharp edges. Now you know where to watch your fingers.</p>
]]></content:encoded></item><item><title><![CDATA[Middleware in Express]]></title><description><![CDATA[Every HTTP request that hits your Express server has a journey to make from the moment it arrives to the moment a response goes back. Middleware is what lives in between.
The Simplest Definition
Middl]]></description><link>https://blogs.satpal.cloud/middleware-in-express</link><guid isPermaLink="true">https://blogs.satpal.cloud/middleware-in-express</guid><category><![CDATA[Express]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[ChaiCode]]></category><dc:creator><![CDATA[Satpalsinh Rana]]></dc:creator><pubDate>Sat, 09 May 2026 12:46:58 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/fff30718-fcf8-4809-9ed5-1b059bfea1d8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Every HTTP request that hits your Express server has a journey to make from the moment it arrives to the moment a response goes back. Middleware is what lives in between.</p>
<h2>The Simplest Definition</h2>
<p>Middleware is a function that runs <em>between</em> the incoming request and the final route handler.</p>
<p>That's it. Any function in Express that receives <code>req</code>, <code>res</code>, and <code>next</code> is middleware.</p>
<pre><code class="language-javascript">function myMiddleware(req, res, next) {
  // do something with the request or response
  next(); // pass control to the next function
}
</code></pre>
<p>Three parameters. That's the signature. The <code>next</code> function is what makes it middleware rather than a route handler calling <code>next()</code> says "I'm done, pass this request to whoever is registered next."</p>
<h2>Middleware in the Request Lifecycle</h2>
<p>Think of every Express request as going through a pipeline — a series of checkpoints before it reaches the final destination. Each checkpoint can inspect the request, modify it, add data to it, block it entirely, or pass it through.</p>
<pre><code class="language-plaintext">Incoming request
      ↓
  [Middleware 1]   ← logging: log method + URL, call next()
      ↓
  [Middleware 2]   ← auth: check token, call next() or return 401
      ↓
  [Middleware 3]   ← body parser: parse JSON into req.body, call next()
      ↓
  [Route handler]  ← do the actual work, send the response
      ↓
Outgoing response
</code></pre>
<p>Every function in that chain gets the same <code>req</code> and <code>res</code> objects. If middleware attaches something to <code>req</code> say, <code>req.user = decodedToken</code> every function after it in the chain can access <code>req.user</code>. This is how authentication middleware passes the authenticated user to a route handler.</p>
<h2>The <code>next()</code> Function</h2>
<p><code>next()</code> is what keeps the chain alive. When middleware calls <code>next()</code>, Express moves to the next registered function. When middleware doesn't call <code>next()</code> (and doesn't send a response either), the request just hangs. The client waits forever. This is one of the most common Express bugs a middleware that silently swallows requests.</p>
<pre><code class="language-javascript">// Correct — always either call next() or send a response
function checkHeader(req, res, next) {
  if (!req.headers['x-api-key']) {
    return res.status(401).json({ error: 'API key required' });
    // we're done — no next() needed, response is sent
  }
  next(); // key exists — move on
}
</code></pre>
<p>Two exits: send a response (and stop), or call <code>next()</code> (and continue). Every middleware must do one of the two.</p>
<p><strong>What most tutorials don't explain about</strong> <code>next()</code><strong>:</strong> you can pass an argument to <code>next()</code>. Passing anything (by convention, an error object) skips all remaining regular middleware and jumps directly to an <em>error-handling</em> middleware:</p>
<pre><code class="language-javascript">function riskyOperation(req, res, next) {
  try {
    const result = doSomethingDangerous();
    next();
  } catch (err) {
    next(err); // skip to error handler
  }
}

// Error-handling middleware: 4 parameters, always (err, req, res, next)
app.use((err, req, res, next) =&gt; {
  console.error(err);
  res.status(500).json({ error: 'Something went wrong' });
});
</code></pre>
<p>The four-parameter signature is Express's convention for error handlers. Express identifies them specifically by the number of parameters not by name, not by position, just by arity. If you write <code>(err, req, res, next)</code>, Express treats it as an error handler and only calls it when <code>next(err)</code> is called somewhere upstream.</p>
<h2>Types of Middleware</h2>
<h3>Application-level middleware</h3>
<p>Registered on the <code>app</code> object with <code>app.use()</code>. Runs for every matching request.</p>
<pre><code class="language-javascript">// Runs for every request, every path
app.use((req, res, next) =&gt; {
  console.log(`\({req.method} \){req.url}`);
  next();
});

// Runs only for requests to /api/*
app.use('/api', (req, res, next) =&gt; {
  console.log('API request received');
  next();
});
</code></pre>
<h3>Router-level middleware</h3>
<p>The same concept, but attached to an <code>express.Router()</code> instance instead of the app. This is how you apply middleware only to a subset of routes:</p>
<pre><code class="language-javascript">const router = express.Router();

// Applies to all routes in this router
router.use((req, res, next) =&gt; {
  console.log('Router-level middleware');
  next();
});

router.get('/profile', (req, res) =&gt; {
  res.json({ user: req.user });
});

app.use('/users', router);
</code></pre>
<p>If you mount this router at <code>/users</code>, the middleware only runs for requests to <code>/users/*</code>.</p>
<h3>Built-in middleware</h3>
<p>Express ships with a few middleware functions out of the box — no extra packages needed:</p>
<p><code>express.json()</code> — parses request bodies with <code>Content-Type: application/json</code>. Makes them available as <code>req.body</code>.</p>
<pre><code class="language-javascript">app.use(express.json());
</code></pre>
<p><code>express.urlencoded({ extended: true })</code> — parses URL-encoded form data (the kind HTML forms submit). Makes it available as <code>req.body</code>.</p>
<pre><code class="language-javascript">app.use(express.urlencoded({ extended: true }));
</code></pre>
<p><code>express.static(directory)</code> — serves static files (HTML, CSS, images, JS) from a folder.</p>
<pre><code class="language-javascript">app.use(express.static('public')); // serves files from ./public
</code></pre>
<p>These are the ones you'll register on almost every Express app. There's also <code>express.raw()</code> and <code>express.text()</code> for other content types, but they're less commonly needed.</p>
<h2>Execution Order:</h2>
<p>Middleware runs in the exact order it's registered. There are no priorities, no weights just top to bottom.</p>
<pre><code class="language-js">app.use(loggerMiddleware);      // 1 — runs first
app.use(express.json());        // 2 — then body parsing
app.use(authMiddleware);        // 3 — then authentication

app.get('/dashboard', (req, res) =&gt; {
  // 4 — route handler (only if all middleware called next())
  res.json({ page: 'dashboard', user: req.user });
});
</code></pre>
<p>A request to <code>GET /dashboard</code> runs through all four in sequence. If <code>authMiddleware</code> returns a <code>401</code>, the route handler never runs.</p>
<p><strong>What happens with multiple route handlers matching the same path?</strong> They run in order too. This is less obvious but occasionally useful:</p>
<pre><code class="language-js">app.get('/users/:id', loadUser);     // attaches user to req
app.get('/users/:id', checkAccess);  // verifies req.user can see this user
app.get('/users/:id', sendResponse); // sends the response
</code></pre>
<p>Three separate handler registrations for the same route. Each calls <code>next()</code> to pass to the next. This is called "route chaining" and it's a valid (if uncommon) pattern for decomposing complex route logic.</p>
<h2>Real-World Examples</h2>
<h3>Logging middleware</h3>
<pre><code class="language-javascript">function logger(req, res, next) {
  const start = Date.now();

  // Intercept res.end to know when the response was sent
  const originalEnd = res.end.bind(res);
  res.end = function (...args) {
    const duration = Date.now() - start;
    console.log(`\({req.method} \){req.url} \({res.statusCode} — \){duration}ms`);
    return originalEnd(...args);
  };

  next();
}

app.use(logger);
</code></pre>
<p>Middleware is a conveyor belt. Each station on the belt can inspect the item, stamp it, reject it, or pass it along. The <code>req</code> and <code>res</code> objects are the item they get passed from station to station. <code>next()</code> is the button that moves the belt forward.</p>
<p>Some stations are always running (global middleware). Some only activate for certain routes. Some are fail-safes at the end (error handlers). Together, they turn a raw HTTP request into a handled, validated, authenticated, logged transaction.</p>
<p>Once you see Express this way, the whole framework clicks.</p>
]]></content:encoded></item><item><title><![CDATA[URL Parameters vs Query Strings in Express.js]]></title><description><![CDATA[Every Express route you write is dealing with URLs. And URLs carry information in more than one way. Two of the most common URL parameters and query strings look similar on the surface but serve very ]]></description><link>https://blogs.satpal.cloud/url-params-vs-query-strings</link><guid isPermaLink="true">https://blogs.satpal.cloud/url-params-vs-query-strings</guid><category><![CDATA[Express]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[ChaiCode]]></category><dc:creator><![CDATA[Satpalsinh Rana]]></dc:creator><pubDate>Sat, 09 May 2026 12:27:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/3fe2ebe0-6db5-4711-be45-5b66130f728f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Every Express route you write is dealing with URLs. And URLs carry information in more than one way. Two of the most common URL parameters and query strings look similar on the surface but serve very different purposes.</p>
<h2>Anatomy of a URL</h2>
<p>Before distinguishing between the two, let's look at a URL in full:</p>
<pre><code class="language-shell">https://api.example.com/users/42/posts?status=published&amp;sort=desc&amp;page=2
</code></pre>
<p>Breaking it apart:</p>
<pre><code class="language-plaintext">https://              ← protocol
api.example.com       ← host
/users/42/posts       ← path (contains a URL parameter: 42)
?                     ← query string delimiter
status=published      ← query parameter 1
&amp;sort=desc            ← query parameter 2
&amp;page=2               ← query parameter 3
</code></pre>
<p>The path is everything before the <code>?</code>. The query string is everything after it. URL parameters live <em>in the path</em>. Query parameters live <em>after the</em> <code>?</code>.</p>
<h2>What URL Parameters Are</h2>
<p>A URL parameter (also called a route parameter or path parameter) is a named placeholder <em>inside the URL path</em> that captures a dynamic value.</p>
<p>In Express, you mark a parameter with a colon:</p>
<pre><code class="language-javascript">app.get('/users/:id', (req, res) =&gt; {
  console.log(req.params.id); // "42" (always a string)
});
</code></pre>
<p>When a request arrives for <code>/users/42</code>, Express extracts <code>42</code> from that position in the path and puts it in <a href="http://req.params.id"><code>req.params.id</code></a>.</p>
<p>You can have multiple parameters:</p>
<pre><code class="language-javascript">app.get('/users/:userId/posts/:postId', (req, res) =&gt; {
  console.log(req.params.userId); // "7"
  console.log(req.params.postId); // "103"
});
</code></pre>
<p>A request to <code>/users/7/posts/103</code> populates both. The parameter name in <code>:paramName</code> is the key in <code>req.params</code>.</p>
<p><strong>The defining characteristic of URL parameters:</strong> they identify <em>which resource</em> you're talking about. Remove the parameter and the URL refers to a completely different resource — or nothing at all.</p>
<pre><code class="language-plaintext">/users/42    → user with id 42
/users/99    → user with id 99 (different resource)
/users       → the users collection (entirely different resource)
</code></pre>
<p>The parameter is structural. It's load-bearing. The URL doesn't make sense without it.</p>
<h2>What Query Strings Are</h2>
<p>A query string is a set of key-value pairs appended to the URL after a <code>?</code>. They're optional the URL is still valid and meaningful without them.</p>
<p>In Express, query parameters live in <code>req.query</code>:</p>
<pre><code class="language-javascript">app.get('/users', (req, res) =&gt; {
  console.log(req.query.role);   // "admin"
  console.log(req.query.sort);   // "created_at"
  console.log(req.query.order);  // "desc"
});
</code></pre>
<p>A request to <code>/users?role=admin&amp;sort=created_at&amp;order=desc</code> produces that output. If none of those query params were sent, the route still matches <code>/users</code> <code>req.query</code> would just be an empty object <code>{}</code>.</p>
<p><strong>The defining characteristic of query parameters:</strong> they <em>modify</em> or <em>filter</em> a request. Remove a query param and you get more results, different ordering, or a different page but you're still talking about the same resource.</p>
<pre><code class="language-plaintext">/users                               → all users, default order
/users?sort=name                     → all users, sorted by name
/users?role=admin                    → only admins
/users?role=admin&amp;sort=name&amp;page=2   → second page of admins, sorted by name
</code></pre>
<p>The resource (<code>/users</code>) is the same. The query params shape how that resource is returned.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/cdf14672-c324-43ed-a970-b666832a2b23.png" alt="" style="display:block;margin:0 auto" />

<h2>Accessing Params in Express: <code>req.params</code></h2>
<p><code>req.params</code> is an object containing all named URL parameters defined in your route.</p>
<pre><code class="language-javascript">app.get('/posts/:postId/comments/:commentId', (req, res) =&gt; {
  const { postId, commentId } = req.params;

  // Always strings — always parseInt or Number() them
  const post    = parseInt(postId);
  const comment = parseInt(commentId);

  res.json({ post, comment });
});
</code></pre>
<p>Request: <code>GET /posts/5/comments/88</code> Response: <code>{ "post": 5, "comment": 88 }</code></p>
<p><strong>The string trap:</strong> <code>req.params</code> values are always strings, even if they look like numbers. <a href="http://req.params.id"><code>req.params.id</code></a> <code>=== 42</code> will always be <code>false</code> because you're comparing <code>"42"</code> (string) to <code>42</code> (number). Always convert before comparing or using in arithmetic.</p>
<pre><code class="language-javascript">const id = parseInt(req.params.id);
// or
const id = Number(req.params.id);
</code></pre>
<p>If the parameter might not be a number (like a username or slug), keep it as a string and use it directly.</p>
<p><strong>Optional parameters:</strong> Express supports optional segments with <code>?</code>:</p>
<pre><code class="language-javascript">app.get('/users/:id?', (req, res) =&gt; {
  if (req.params.id) {
    res.json({ user: req.params.id });
  } else {
    res.json({ users: 'all' });
  }
});
</code></pre>
<p>A single route handles both <code>/users</code> and <code>/users/42</code>. Useful, but in practice it's usually cleaner to keep these as separate routes. Combining them adds complexity for little gain.</p>
<p>Express allows you to define pre-processing logic for a named parameter using <code>app.param()</code>:</p>
<pre><code class="language-javascript">app.param('id', (req, res, next, id) =&gt; {
  const parsed = parseInt(id);
  if (isNaN(parsed)) {
    return res.status(400).json({ error: 'ID must be a number' });
  }
  req.params.id = parsed; // replace the string with the number
  next();
});

// Now every route using :id gets a pre-validated integer
app.get('/users/:id', (req, res) =&gt; {
  // req.params.id is already a number here — no parseInt needed
  res.json({ id: req.params.id });
});
</code></pre>
<p>This runs before any route handler that includes <code>:id</code>. You validate and transform once, and every handler benefits. This is one of Express's more underused features.</p>
<h2>Accessing Query Strings in Express: <code>req.query</code></h2>
<p><code>req.query</code> is an object containing all query parameters. Express parses the query string automatically — no setup required.</p>
<pre><code class="language-javascript">app.get('/products', (req, res) =&gt; {
  const {
    category,           // string or undefined
    minPrice,           // string or undefined
    maxPrice,           // string or undefined
    sort = 'name',      // default to 'name' if not provided
    page = '1',         // default to '1'
    limit = '20',
  } = req.query;

  // Parse numeric values
  const min  = minPrice ? parseFloat(minPrice) : 0;
  const max  = maxPrice ? parseFloat(maxPrice) : Infinity;
  const pg   = parseInt(page);
  const lim  = parseInt(limit);

  res.json({ category, min, max, sort, pg, lim });
});
</code></pre>
<p>Request: <code>GET /products?category=electronics&amp;minPrice=50&amp;sort=price</code></p>
<p>Response:</p>
<pre><code class="language-json">{
  "category": "electronics",
  "min": 50,
  "max": null,
  "sort": "price",
  "pg": 1,
  "lim": 20
}
</code></pre>
<p>Always default your query params. A request to <code>/products</code> with no query string should still work — <code>req.query</code> will be <code>{}</code> and destructuring gives you <code>undefined</code> for everything. Default values in destructuring handle this cleanly.</p>
<p><strong>The string trap again:</strong> same issue as URL parameters. <code>req.query</code> values are <em>always strings</em>. <a href="http://req.query.page"><code>req.query.page</code></a> <code>=== 1</code> is always <code>false</code>. Parse numbers explicitly.</p>
<p><strong>Arrays in query strings:</strong> Express handles repeated keys as arrays automatically:</p>
<pre><code class="language-plaintext">GET /products?tag=javascript&amp;tag=nodejs&amp;tag=backend
</code></pre>
<pre><code class="language-javascript">app.get('/products', (req, res) =&gt; {
  console.log(req.query.tag); // ['javascript', 'nodejs', 'backend']
});
</code></pre>
<p>But if only one value is sent, <code>req.query.tag</code> is a string, not an array. To always get an array:</p>
<pre><code class="language-javascript">const tags = [].concat(req.query.tag || []);
// or
const tags = Array.isArray(req.query.tag)
  ? req.query.tag
  : req.query.tag ? [req.query.tag] : [];
</code></pre>
<p>This is a common bug in Express APIs code that works fine with multiple tags silently breaks when only one is sent.</p>
<p>Here's a clean mental model:</p>
<p><strong>Use a URL parameter when:</strong></p>
<ul>
<li><p>It identifies a specific resource</p>
</li>
<li><p>The URL is meaningless or broken without it</p>
</li>
<li><p>There's only one logical value for that position</p>
</li>
</ul>
<p><strong>Use a query string when:</strong></p>
<ul>
<li><p>It modifies how a resource (or collection) is returned</p>
</li>
<li><p>It's optional — the endpoint works without it</p>
</li>
<li><p>Multiple key-value pairs might apply simultaneously</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/54db9685-650d-4054-b57a-b46b33609c5d.png" alt="" style="display:block;margin:0 auto" />

<h2>Real-World Scenarios</h2>
<p><strong>User profile:</strong> <code>/users/:id</code></p>
<p>The <code>id</code> is a URL parameter — it <em>identifies</em> the user. Without it, the URL refers to the collection of all users, not this specific person.</p>
<p><strong>User search:</strong> <code>/users?q=alice&amp;role=admin</code></p>
<p>The <code>q</code> and <code>role</code> are query strings — they <em>filter</em> the collection. Without them, you still get users (just all of them).</p>
<p><strong>Blog post:</strong> <code>/posts/:slug</code></p>
<p>The <code>slug</code> is a URL parameter — it identifies this specific article. <code>/posts</code> is the list; <code>/posts/building-rest-apis-with-express</code> is the specific post.</p>
<p><strong>Blog post list:</strong> <code>/posts?tag=nodejs&amp;author=john&amp;page=2</code></p>
<p>All query strings — they modify the list, not the resource identity.</p>
<p><strong>E-commerce product:</strong> <code>/products/:productId</code></p>
<p>URL parameter — identifies the product.</p>
<p><strong>Product reviews:</strong> <code>/products/:productId/reviews?sort=rating&amp;page=1</code></p>
<p>Mixed. <code>:productId</code> is a parameter — which product's reviews. <code>sort</code> and <code>page</code> are query strings — how to return those reviews.</p>
<p>I’m currently deep-diving into the <strong>JavaScript</strong>, building projects and exploring the internals of the web. If you're on a similar journey or just love talking about JavaScript, let’s stay in touch!</p>
<ul>
<li><p><strong>Connect on LinkedIn:</strong> <a href="https://www.linkedin.com/in/satpalsinhrana"><strong>Satpalsinh's Profile</strong></a></p>
</li>
<li><p><strong>Follow my Blog:</strong> <a href="http://blogs.satpal.cloud"><strong>blogs.satpal.cloud</strong></a></p>
</li>
</ul>
<p><strong>Keep coding and keep building.</strong></p>
]]></content:encoded></item><item><title><![CDATA[Creating Routes and Handling Requests with Express.js]]></title><description><![CDATA[Before Express.js existed, building an HTTP server in Node.js meant writing a lot of code just to get started.
What Express.js Actually Is
Express is a minimal web framework for Node.js. That word min]]></description><link>https://blogs.satpal.cloud/start-with-express</link><guid isPermaLink="true">https://blogs.satpal.cloud/start-with-express</guid><category><![CDATA[Express]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[ChaiCode]]></category><dc:creator><![CDATA[Satpalsinh Rana]]></dc:creator><pubDate>Sat, 09 May 2026 12:19:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/ac52455d-5cd5-4947-a52f-f9d51a29a5f4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Before Express.js existed, building an HTTP server in Node.js meant writing a lot of code just to get started.</p>
<h2>What Express.js Actually Is</h2>
<p>Express is a minimal web framework for Node.js. That word minimal is important it doesn't come with an ORM, a templating engine, a validation library, or an authentication system built in. It comes with routing, middleware support, and a cleaner interface around Node's <code>http</code> module.</p>
<p>This is intentional. Express is a foundation, not a full solution. The developer community built the ecosystem around it hundreds of middleware packages that plug in cleanly so you compose exactly what you need, rather than inheriting what a framework decided you should have.</p>
<h2>Raw Node.js vs Express: The Problem It Solves</h2>
<p>Let's see the gap side by side.</p>
<p><strong>Handling two routes in raw Node.js:</strong></p>
<pre><code class="language-javascript">const http = require('http');

const server = http.createServer((req, res) =&gt; {
  if (req.method === 'GET' &amp;&amp; req.url === '/') {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ message: 'Home' }));
  } else if (req.method === 'GET' &amp;&amp; req.url === '/users') {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ users: [] }));
  } else if (req.method === 'POST' &amp;&amp; req.url === '/users') {
    let body = '';
    req.on('data', chunk =&gt; { body += chunk.toString(); });
    req.on('end', () =&gt; {
      const data = JSON.parse(body);
      res.writeHead(201, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify(data));
    });
  } else {
    res.writeHead(404);
    res.end('Not found');
  }
});

server.listen(3000);
</code></pre>
<p><img src="align=%22center%22" alt="" /></p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/d4d33640-9f17-4b5f-bf6b-d4072e6d4b23.png" alt="" style="display:block;margin:0 auto" />

<p>This works. But notice what you're dealing with:</p>
<ul>
<li><p>Manual <code>if/else</code> routing on every request</p>
</li>
<li><p>Checking method and URL manually every time</p>
</li>
<li><p>Manually reading the request body stream in chunks</p>
</li>
<li><p>Manually setting <code>Content-Type</code> headers on every response</p>
</li>
<li><p>No URL parameters (try matching <code>/users/42</code> — you'd need a regex or a URL parser)</p>
</li>
</ul>
<p><strong>The same routes in Express:</strong></p>
<pre><code class="language-javascript">const express = require('express');
const app = express();
app.use(express.json());

app.get('/', (req, res) =&gt; {
  res.json({ message: 'Home' });
});

app.get('/users', (req, res) =&gt; {
  res.json({ users: [] });
});

app.post('/users', (req, res) =&gt; {
  res.status(201).json(req.body);
});

app.listen(3000);
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/cb120153-5e7a-4952-9820-ffb1c2082551.png" alt="" style="display:block;margin:0 auto" />

<p>Express removes all the boilerplate. The routing is declarative. Body parsing is handled by middleware. <code>res.json()</code> sets <code>Content-Type</code> automatically. The intent of every route is immediately obvious.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/1bfa43be-b73e-463f-a03e-4740dd131f51.png" alt="" style="display:block;margin:0 auto" />

<h2>Installing Express</h2>
<pre><code class="language-shell">mkdir my-express-app
cd my-express-app
npm init -y
npm install express
</code></pre>
<p>Create <code>index.js</code> and you're ready.</p>
<h2>Your First Express Server</h2>
<pre><code class="language-javascript">const express = require('express');
const app = express();

app.use(express.json());

app.listen(3000, () =&gt; {
  console.log('Server running on http://localhost:3000');
});
</code></pre>
<p>Three things happening here:</p>
<p><code>require('express')</code> — imports the Express module. Express exports a function; calling it creates an application instance.</p>
<p><code>app.use(express.json())</code> — registers middleware. This specific middleware reads the incoming request body and parses it as JSON, making it available as <code>req.body</code>. Without this line, <code>req.body</code> is <code>undefined</code> for POST requests. It only parses requests with <code>Content-Type: application/json</code> — it doesn't touch form submissions or plain text.</p>
<p><code>app.listen(3000, callback)</code> — binds the server to port 3000. The callback fires once when the server is ready. This is exactly equivalent to creating an <code>http.Server</code> and calling <code>.listen()</code> on it.</p>
<p>Express does that for you internally.</p>
<h2>How Routing Works in Express</h2>
<p>A route is the combination of an HTTP method and a URL path. When a request arrives, Express walks through your registered routes in the order you defined them and calls the first one that matches both the method and the path.</p>
<p>The basic signature is:</p>
<p>js</p>
<pre><code class="language-js">app.METHOD(PATH, HANDLER)
</code></pre>
<p>Where <code>METHOD</code> is <code>get</code>, <code>post</code>, <code>put</code>, <code>delete</code>, <code>patch</code>, or others. <code>PATH</code> is a string (or a regex, or an array). <code>HANDLER</code> is a function that receives <code>req</code> and <code>res</code>.</p>
<pre><code class="language-javascript">app.get('/hello', (req, res) =&gt; {
  res.send('Hello, world');
});
</code></pre>
<p>If a <code>GET</code> request arrives for <code>/hello</code>, this handler runs. If the method is <code>POST</code>, it won't match. If the path is <code>/hello/world</code>, it won't match either (unless you use wildcards).</p>
<p><strong>What most tutorials don't explain:</strong> the order of route definitions matters. Express matches routes top to bottom, first match wins. If you define a broad route before a specific one, the broad one catches the request and the specific one never runs.</p>
<pre><code class="language-javascript">// Broad route defined first — always wins
app.get('/users/*', (req, res) =&gt; {
  res.send('wildcard'); // this matches /users/admin too
});

// This never runs — the route above caught it first
app.get('/users/admin', (req, res) =&gt; {
  res.send('admin panel');
});
</code></pre>
<p>Always define specific routes before general ones.</p>
<h2>Handling GET Requests</h2>
<p>GET is the most common HTTP method fetch data, list resources, retrieve a single item.</p>
<pre><code class="language-javascript">// Simple static route
app.get('/', (req, res) =&gt; {
  res.json({ status: 'ok', version: '1.0' });
});

// List resource
app.get('/products', (req, res) =&gt; {
  const products = [
    { id: 1, name: 'Keyboard', price: 79 },
    { id: 2, name: 'Mouse',    price: 39 },
  ];
  res.status(200).json(products);
});

// Single resource with URL parameter
app.get('/products/:id', (req, res) =&gt; {
  const id = parseInt(req.params.id);
  const product = products.find(p =&gt; p.id === id);

  if (!product) {
    return res.status(404).json({ error: 'Product not found' });
  }

  res.status(200).json(product);
});
</code></pre>
<p><code>:id</code> in the path is a named URL parameter. Express captures whatever is in that position in the URL and puts it in <a href="http://req.params.id"><code>req.params.id</code></a>. More on parameters in the next article for now, know they exist and look like <code>:name</code>.</p>
<h2>Handling POST Requests</h2>
<p>POST is used to create new resources. Data comes in the request body, not the URL.</p>
<pre><code class="language-javascript">app.post('/products', (req, res) =&gt; {
  const { name, price } = req.body;

  // Validate
  if (!name || price === undefined) {
    return res.status(400).json({ error: 'name and price are required' });
  }

  if (typeof price !== 'number' || price &lt; 0) {
    return res.status(400).json({ error: 'price must be a non-negative number' });
  }

  // Create
  const newProduct = {
    id: Date.now(), // simple ID for demo
    name,
    price,
  };

  res.status(201).json(newProduct);
});
</code></pre>
<p><code>req.body</code> works because <code>express.json()</code> middleware ran first and parsed the request body. If the client sends <code>Content-Type: application/json</code> and valid JSON in the body, <code>req.body</code> will be a JavaScript object.</p>
<p>The <code>return</code> before each error response is critical. Without it, Express attempts to send a second response after the first <code>res.json()</code> call, which throws a <code>"Cannot set headers after they are sent"</code> error. The <code>return</code> exits the handler function immediately.</p>
<p>What happens when the client sends invalid JSON? If the body is malformed, <code>express.json()</code> will respond with a <code>400</code> error automatically before your handler even runs. You don't need to handle JSON parse errors yourself — the middleware does it. But if you want to customize that error response (to match your API's error format), you can add an error-handling middleware:</p>
<pre><code class="language-javascript">app.use((err, req, res, next) =&gt; {
  if (err.type === 'entity.parse.failed') {
    return res.status(400).json({ error: 'Invalid JSON in request body' });
  }
  next(err);
});
</code></pre>
<p>The four-parameter signature <code>(err, req, res, next)</code> is Express's convention for error-handling middleware. It only runs when an error is passed or thrown.</p>
<h2>Sending Responses</h2>
<p>Express's <code>res</code> object extends Node's built-in response, adding helper methods that handle headers automatically.</p>
<p><code>res.json(data)</code> — sends a JSON response. Sets <code>Content-Type: application/json</code> and <code>status 200</code> automatically. Calls <code>JSON.stringify</code> internally.</p>
<pre><code class="language-javascript">res.json({ id: 1, name: 'Alice' });
</code></pre>
<p><code>res.status(code)</code> — sets the HTTP status code. It returns <code>res</code> so you can chain it:</p>
<pre><code class="language-javascript">res.status(201).json({ id: 1, name: 'Alice' }); // 201 Created
res.status(404).json({ error: 'Not found' });    // 404 Not Found
</code></pre>
<p><code>res.send(body)</code> — sends a response. If you pass a string, <code>Content-Type</code> is <code>text/html</code>. If you pass an object, it behaves like <code>res.json()</code>. Prefer <code>res.json()</code> for APIs — it's explicit about the content type.</p>
<p><code>res.status(204).send()</code> — sends an empty response. Required for DELETE endpoints where there's no body to return.</p>
<p><code>res.set(header, value)</code> — sets a custom response header:</p>
<pre><code class="language-javascript">res.set('X-Request-Id', 'abc123').json({ data: '...' });
</code></pre>
<p><strong>What most developers don't know about</strong> <code>res.json()</code><strong>:</strong> it runs <code>JSON.stringify</code> with the <code>json spaces</code> app setting. You can configure pretty-printing for development:</p>
<pre><code class="language-javascript">app.set('json spaces', 2); // pretty-print JSON in development
</code></pre>
<p>This makes responses human-readable in development without changing your code. Set it conditionally:</p>
<pre><code class="language-javascript">if (process.env.NODE_ENV !== 'production') {
  app.set('json spaces', 2);
}
</code></pre>
<h2>A Complete Working Server</h2>
<p>Here's everything put together — a small but complete server covering multiple routes and both methods:</p>
<pre><code class="language-javascript">const express = require('express');
const app = express();

app.use(express.json());

// In-memory store
let books = [
  { id: 1, title: 'The Pragmatic Programmer', author: 'Hunt &amp; Thomas' },
  { id: 2, title: 'Clean Code',               author: 'Robert Martin'  },
];
let nextId = 3;

// GET all books
app.get('/books', (req, res) =&gt; {
  res.status(200).json(books);
});

// GET one book
app.get('/books/:id', (req, res) =&gt; {
  const book = books.find(b =&gt; b.id === parseInt(req.params.id));
  if (!book) return res.status(404).json({ error: 'Book not found' });
  res.status(200).json(book);
});

// POST create a book
app.post('/books', (req, res) =&gt; {
  const { title, author } = req.body;

  if (!title || !author) {
    return res.status(400).json({ error: 'title and author are required' });
  }

  const book = { id: nextId++, title, author };
  books.push(book);
  res.status(201).json(book);
});

// 404 fallback — must be last
app.use((req, res) =&gt; {
  res.status(404).json({ error: `Cannot \({req.method} \){req.url}` });
});

app.listen(3000, () =&gt; console.log('Running on http://localhost:3000'));
</code></pre>
<h2>Express Router: Splitting Routes Across Files</h2>
<p>As an application grows, keeping every route in <code>index.js</code> becomes unmanageable. Express's <code>Router</code> is a mini-app — it has its own <code>.get()</code>, <code>.post()</code>, <code>.use()</code>, etc. — that you can mount on a path.</p>
<pre><code class="language-javascript">// routes/books.js
const express = require('express');
const router = express.Router();

router.get('/', (req, res) =&gt; {
  res.json(books);
});

router.post('/', (req, res) =&gt; {
  // create book
});

router.get('/:id', (req, res) =&gt; {
  // get one book
});

module.exports = router;
</code></pre>
<pre><code class="language-javascript">// index.js
const booksRouter = require('./routes/books');
app.use('/books', booksRouter);
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/8003e517-026f-4a4e-a032-a35c5d79c69d.png" alt="" style="display:block;margin:0 auto" />

<p>Routers are also just middleware. You can stack multiple routers, nest them, add middleware that only applies to a specific router, and reuse them across different mount points. The same <code>booksRouter</code> mounted at <code>/api/v1/books</code> and <code>/api/v2/books</code> would serve both paths from the same code.</p>
<p>Understand what Express does under the hood (it's mostly Node's <code>http</code> module with a layer on top) and you'll never be confused by its behavior. Understand how route matching works (top-down, first match wins) and you'll never write a route that silently never runs.</p>
<p>I’m currently deep-diving into the <strong>JavaScript</strong>, building projects and exploring the internals of the web. If you're on a similar journey or just love talking about JavaScript, let’s stay in touch!</p>
<ul>
<li><p><strong>Connect on LinkedIn:</strong> <a href="https://www.linkedin.com/in/satpalsinhrana"><strong>Satpalsinh's Profile</strong></a></p>
</li>
<li><p><strong>Follow my Blog:</strong> <a href="http://blogs.satpal.cloud"><strong>blogs.satpal.cloud</strong></a></p>
</li>
</ul>
<p><strong>Keep coding and keep building.</strong></p>
]]></content:encoded></item><item><title><![CDATA[REST API Design Made Simple with Express.js]]></title><description><![CDATA[What Is an API?
API stands for Application Programming Interface. Ignore the formal definition for a moment and think about what's actually happening.
You have a client a browser, a mobile app, a CLI ]]></description><link>https://blogs.satpal.cloud/rest-api-express-js</link><guid isPermaLink="true">https://blogs.satpal.cloud/rest-api-express-js</guid><category><![CDATA[Express]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[ChaiCode]]></category><dc:creator><![CDATA[Satpalsinh Rana]]></dc:creator><pubDate>Sat, 09 May 2026 11:44:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/4c2797c7-626d-4097-9a06-6454afc17462.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>What Is an API?</h2>
<p>API stands for Application Programming Interface. Ignore the formal definition for a moment and think about what's actually happening.</p>
<p>You have a client a browser, a mobile app, a CLI tool, another server and you have a server that knows things or can do things the client needs. The API is the agreed upon language they use to talk.</p>
<p>When a user logs into an app, the frontend doesn't just magically know their data.</p>
<p>It sends a request to the server:<br /><em>"Hey, here's a username and password — does this check out? If so, give me this user's profile."</em></p>
<p>The server checks, and responds:<br /><em>"Yes, here it is."</em></p>
<p>That exchange, the format of the request, the format of the response is the API.</p>
<p>REST is a specific way of designing that exchange. It uses HTTP (the same protocol your browser uses to load web pages) and a set of conventions that make APIs predictable and consistent.</p>
<h2>The Core Idea</h2>
<p>REST stands for Representational State Transfer. The jargon doesn't help much. What <em>does</em> help is understanding the concept of a <strong>resource</strong>.</p>
<p>In REST, everything you expose through your API is a <em>resource</em> — a noun, a thing. Users are a resource. Posts are a resource. Orders, products, comments — all resources.</p>
<p>Each resource has a URL that identifies it. That URL is called an <strong>endpoint</strong>. The naming convention is clean: always use plural nouns, always lowercase, no verbs.</p>
<pre><code class="language-plaintext">Good:
  /users
  /users/42
  /posts
  /posts/7/comments

Bad:
  /getUsers
  /deleteUser?id=42
  /createNewPost
</code></pre>
<p>The bad examples describe <em>actions</em>, not resources. The action is communicated via the HTTP method, not the URL. The URL should only tell you <em>what</em> you're operating on the HTTP method tells you <em>how</em>.</p>
<h2>HTTP Methods: The Verbs of REST</h2>
<p>HTTP ships with a set of methods sometimes called verbs that describe the intended operation on a resource. REST maps these directly to the four classic database operations known as CRUD: Create, Read, Update, Delete.</p>
<p><strong>GET</strong> — Retrieve a resource. Read-only. Should never modify anything. Safe to call multiple times.</p>
<p><strong>POST</strong> — Create a new resource. Sends data in the request body. Used when the server generates the ID.</p>
<p><strong>PUT</strong> — Replace an existing resource entirely. You send the full updated version, the server stores it as-is.</p>
<p><strong>DELETE</strong> — Remove a resource.</p>
<p>There's also <strong>PATCH</strong>, which is worth knowing even though it's less universal: it partially updates a resource. Where <code>PUT</code> replaces everything, <code>PATCH</code> just changes the fields you send. For a user profile, <code>PUT</code> would require sending name + email + age + every other field even if you're only changing the email. <code>PATCH</code> lets you send just <code>{ "email": "</code><a href="mailto:new@email.com"><code>new@email.com</code></a><code>" }</code>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/e884c1ec-8734-4245-bf68-0fb252c54183.png" alt="" style="display:block;margin:0 auto" />

<h2>Status Codes: The Server's Reply</h2>
<p>When your server responds, it includes a status code a three-digit number that tells the client whether things went well, and if not, why not. Most developers know 404. There are many more.</p>
<p>The codes are grouped by their first digit:</p>
<p><strong>2xx — Success</strong></p>
<ul>
<li><p><code>200 OK</code> — generic success. Used for successful GET, PUT, PATCH responses.</p>
</li>
<li><p><code>201 Created</code> — resource was successfully created (POST responses).</p>
</li>
<li><p><code>204 No Content</code> — success, but nothing to return (DELETE responses).</p>
</li>
</ul>
<p><strong>4xx — Client errors</strong> (the request was wrong)</p>
<ul>
<li><p><code>400 Bad Request</code> — the client sent malformed data.</p>
</li>
<li><p><code>401 Unauthorized</code> — no authentication was provided.</p>
</li>
<li><p><code>403 Forbidden</code> — authenticated but not allowed.</p>
</li>
<li><p><code>404 Not Found</code> — the resource doesn't exist.</p>
</li>
<li><p><code>409 Conflict</code> — the request conflicts with current state (e.g. duplicate email).</p>
</li>
<li><p><code>422 Unprocessable Entity</code> — data was well-formed but failed validation.</p>
</li>
</ul>
<p><strong>5xx — Server errors</strong> (something broke on your end)</p>
<ul>
<li><p><code>500 Internal Server Error</code> — generic catch-all server failure.</p>
</li>
<li><p><code>503 Service Unavailable</code> — server is down or overloaded.</p>
</li>
</ul>
<p><code>401</code> vs <code>403</code> is a distinction almost every junior API makes incorrectly. <code>401</code> means "who are you? I don't know you." <code>403</code> means "I know who you are, but you can't do this." If a user is logged in and tries to access another user's private data, that's a <code>403</code>, not a <code>401</code>. If there's no token at all, it's a <code>401</code>.</p>
<p>Also: <code>404</code> vs <code>403</code> for private resources is a deliberate security decision. If a user asks for <code>/users/99</code> and that user exists but belongs to someone else, should you return <code>404</code> (pretend it doesn't exist) or <code>403</code> (admit it exists but deny access)? Returning <code>404</code> is often the more secure choice it doesn't reveal which IDs exist.</p>
<h2>Designing the Users Resource</h2>
<p>Let's build a complete CRUD API for a <code>users</code> resource. In a real app you'd use a database here we'll use an in-memory array to keep the focus on the API design.</p>
<p>GET /users — List all users</p>
<p>GET /users/:id — Get one user</p>
<p>POST /users — Create a new user</p>
<p>PUT /users/:id — Replace a user</p>
<p>DELETE /users/:id — Remove a user</p>
<h2>Route Naming: The Conventions That Actually Matter</h2>
<p>These conventions aren't enforced by any framework. They're just what every experienced developer expects, which is exactly why they matter:</p>
<p><strong>Use nouns, not verbs in URLs.</strong></p>
<ul>
<li><code>/users</code> not <code>/getUsers</code>, <code>/createUser</code>, <code>/deleteUser</code></li>
</ul>
<p><strong>Use plural nouns for collections.</strong></p>
<ul>
<li><p><code>/users</code> not <code>/user</code></p>
</li>
<li><p><code>/posts</code> not <code>/post</code></p>
</li>
</ul>
<p><strong>Use URL parameters for specific resources.</strong></p>
<ul>
<li><code>/users/42</code> not <code>/users?id=42</code></li>
</ul>
<p><strong>Use query strings for filtering, sorting, pagination.</strong></p>
<ul>
<li><p><code>/users?role=admin</code> — filter by role</p>
</li>
<li><p><code>/users?sort=created_at&amp;order=desc</code> — sorted list</p>
</li>
<li><p><code>/users?page=2&amp;limit=20</code> — pagination</p>
</li>
</ul>
<p><strong>Nested resources for relationships.</strong></p>
<ul>
<li><p><code>/users/42/posts</code> — all posts by user 42</p>
</li>
<li><p><code>/users/42/posts/7</code> — a specific post by user 42</p>
</li>
</ul>
<p><strong>What most developers don't think about:</strong> versioning. When your API is public or consumed by mobile apps you don't control, you'll eventually need to change it in a breaking way. The standard solution is URL versioning: <code>/api/v1/users</code>, <code>/api/v2/users</code>. It's something you should add from the start, not retrofit later.</p>
<h2>Error Consistency:</h2>
<p>One thing that separates a professional API from a tutorial API: consistent error responses. Your errors should all look the same.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/423ba235-a707-413d-9fa7-0fed05cbf944.png" alt="" style="display:block;margin:0 auto" />

<p>REST API design is largely a discipline of making decisions <em>before</em> you start coding and sticking to them. The decisions aren't hard: plural nouns, HTTP methods as verbs, correct status codes, consistent error shapes. None of these require advanced knowledge they just require intention.</p>
<p>Express.js gives you the minimum to implement all of this. No magic, no opinions just a router, middleware support, and <code>req</code>/<code>res</code>. The REST conventions layer on top cleanly.</p>
<p>Master one resource, get all the conventions right, and every other resource you add will look exactly the same. That's the whole point of REST: uniformity. Once a developer learns how one endpoint works, they understand how all of them work.</p>
<p>I’m currently deep-diving into the <strong>JavaScript</strong>, building projects and exploring the internals of the web. If you're on a similar journey or just love talking about JavaScript, let’s stay in touch!</p>
<ul>
<li><p><strong>Connect on LinkedIn:</strong> <a href="https://www.linkedin.com/in/satpalsinhrana"><strong>Satpalsinh's Profile</strong></a></p>
</li>
<li><p><strong>Follow my Blog:</strong> <a href="http://blogs.satpal.cloud"><strong>blogs.satpal.cloud</strong></a></p>
</li>
</ul>
<p><strong>Keep coding and keep building.</strong></p>
]]></content:encoded></item><item><title><![CDATA[Callbacks and Promises]]></title><description><![CDATA[In our previous article we have seen that why we need async code. In this we will go through how to write async code
Callbacks
A callback is the simplest possible async mechanism: pass a function as a]]></description><link>https://blogs.satpal.cloud/callbacks-and-promises</link><guid isPermaLink="true">https://blogs.satpal.cloud/callbacks-and-promises</guid><dc:creator><![CDATA[Satpalsinh Rana]]></dc:creator><pubDate>Sat, 09 May 2026 11:20:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/3cd08aec-8e49-4d73-87c2-a0e5eb02c317.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In our previous article we have seen that why we need async code. In this we will go through how to write async code</p>
<h2>Callbacks</h2>
<p>A callback is the simplest possible async mechanism: pass a function as an argument, and Node.js will call it when the async work is done.</p>
<p>Here's the pattern, using <code>fs.readFile</code> as the canonical example</p>
<pre><code class="language-javascript">const fs = require('fs');

fs.readFile('./config.json', 'utf8', function(err, data) {
  if (err) {
    console.error('Failed to read file:', err);
    return;
  }
  console.log(data);
});

console.log('This runs immediately — before the file is read');
</code></pre>
<p>Notice two things about this pattern:</p>
<ol>
<li><p>Error-first convention. Node.js callbacks always receive the error as the first argument. If there's no error, it's null. If there is an error, the data argument will be undefined. This is called the "error-first" or "Node.js callback style." It's a convention, not enforced by the language but almost every Node.js built-in and npm package follows it. Always check err before using data.</p>
</li>
<li><p>Execution order. The console.log at the bottom runs before the file contents print. The readFile call registers the callback and returns immediately. The callback fires later, when the OS finishes reading. This is the async reordering you saw in the event loop article and it's always the behavior with callbacks.</p>
</li>
</ol>
<h2>Callbacks in Practice: A Real Scenario</h2>
<p>Say you need to:</p>
<ol>
<li><p>Read a user's config file</p>
</li>
<li><p>Parse it as JSON</p>
</li>
<li><p>Use the <code>userId</code> from the config to fetch user data from a database</p>
</li>
<li><p>Log the user's name</p>
</li>
</ol>
<pre><code class="language-javascript">const fs = require('fs');

fs.readFile('./config.json', 'utf8', function(err, data) {
  if (err) {
    console.error('Could not read config:', err);
    return;
  }

  let config;
  try {
    config = JSON.parse(data);
  } catch (parseErr) {
    console.error('Config is not valid JSON:', parseErr);
    return;
  }

  db.findUser(config.userId, function(err, user) {
    if (err) {
      console.error('Could not fetch user:', err);
      return;
    }

    console.log('User:', user.name);
  });
});
</code></pre>
<p>This works. It's perfectly valid Node.js code. But notice what happened to the structure: every async step requires nesting inside the previous one's callback. And we only have three operations. Real applications often have five, eight, ten.</p>
<h3>Callback Hell</h3>
<p>The nesting problem has a name in the Node.js community: <strong>callback hell</strong> — sometimes called the "pyramid of doom" because of the shape the indentation makes.</p>
<p>Here's what five sequential async steps looks like with callbacks:</p>
<pre><code class="language-javascript">readFile(path, function(err, data) {
  if (err) return handleError(err);
  parseConfig(data, function(err, config) {
    if (err) return handleError(err);
    fetchUser(config.userId, function(err, user) {
      if (err) return handleError(err);
      fetchPermissions(user.id, function(err, perms) {
        if (err) return handleError(err);
        generateReport(user, perms, function(err, report) {
          if (err) return handleError(err);
          console.log(report);
        });
      });
    });
  });
});
</code></pre>
<p>This is technically correct but practically painful:</p>
<ul>
<li><p>Every level of nesting adds cognitive load</p>
</li>
<li><p>Error handling must be repeated at every step</p>
</li>
<li><p>You can't reuse a step independently — everything is tangled together</p>
</li>
<li><p>Adding a sixth step means another level of indentation</p>
</li>
<li><p>Debugging means mentally tracking which variables are in scope at which nesting depth</p>
</li>
</ul>
<p>The code describes what happens in the right order, but it doesn't <em>read</em> that way. You can't scan it top-to-bottom and understand the flow linearly.</p>
<p>You can partially escape callback hell without Promises by naming your callbacks and defining them separately instead of inline. The same five-step sequence above can be written flat if you define each callback as a named function. It's not as ergonomic as Promises, but it's far more readable than nested inline functions. Many legacy Node.js codebases use exactly this pattern.</p>
<h1>Promises</h1>
<p>A Promise is an object that represents the <em>eventual result</em> of an async operation. Instead of passing a callback <em>into</em> a function, the function returns a Promise object that you work with.</p>
<p>The Promise can be in one of three states:</p>
<ul>
<li><p><strong>Pending</strong> — the operation is still in progress</p>
</li>
<li><p><strong>Fulfilled</strong> — the operation succeeded; the result is available</p>
</li>
<li><p><strong>Rejected</strong> — the operation failed; an error is available</p>
</li>
</ul>
<p>Once a Promise settles (fulfills or rejects), it stays that way forever. It won't randomly fulfill again, or change its result. This immutability is one of the things that makes Promises easier to reason about than callbacks.</p>
<p>Here's the same file-read example with a Promise-based API:</p>
<pre><code class="language-javascript">const fs = require('fs').promises;

fs.readFile('./config.json', 'utf8')
  .then(function(data) {
    console.log(data);
  })
  .catch(function(err) {
    console.error('Failed to read file:', err);
  });
</code></pre>
<p>The <code>.then()</code> runs when the Promise fulfills. The <code>.catch()</code> runs if it rejects. And critically you can chain them.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/bf228496-d164-4ebb-86d9-39519969dac0.png" alt="" style="display:block;margin:0 auto" />

<h3>Chaining</h3>
<p>Here's the power move. Instead of nesting, you chain <code>.then()</code> calls in a flat sequence:</p>
<pre><code class="language-javascript">const fs = require('fs').promises;

fs.readFile('./config.json', 'utf8')
  .then(data =&gt; JSON.parse(data))           // step 2: parse
  .then(config =&gt; db.findUser(config.userId)) // step 3: fetch user
  .then(user =&gt; {
    console.log('User:', user.name);
  })
  .catch(err =&gt; {
    console.error('Something went wrong:', err); // catches errors from ANY step
  });
</code></pre>
<p>Compare this to the callback version. It's the same five operations, written flat, with a single <code>.catch()</code> at the end that handles any error from any step.</p>
<p><strong>This is why Promises were adopted so rapidly.</strong> The logic flows top to bottom. You can read it and understand the sequence. Error handling is centralized. Each <code>.then()</code> receives the return value of the previous one so passing data from step to step is just a matter of returning it.</p>
<h2>Creating Your Own Promises</h2>
<p>You won't just consume Promises — you'll need to wrap older callback-based code in them. Here's how:</p>
<pre><code class="language-javascript">function readFileAsync(path) {
  return new Promise(function(resolve, reject) {
    fs.readFile(path, 'utf8', function(err, data) {
      if (err) {
        reject(err);    // → Promise rejects with the error
      } else {
        resolve(data);  // → Promise fulfills with the data
      }
    });
  });
}

// Now you can use it with .then()/.catch()
readFileAsync('./data.txt')
  .then(data =&gt; console.log(data))
  .catch(err =&gt; console.error(err));
</code></pre>
<p>The <code>new Promise(executor)</code> pattern: inside the executor function, you call <code>resolve(value)</code> when the work succeeds and <code>reject(error)</code> when it fails. The Promise object carries that result forward.</p>
<p><strong>What most tutorials skip:</strong> Node.js ships with <code>util.promisify()</code>, a built-in utility that automatically wraps any error-first callback function into a Promise-returning function. Instead of writing the wrapper above manually:</p>
<pre><code class="language-javascript">const { promisify } = require('util');
const readFileAsync = promisify(fs.readFile);

readFileAsync('./data.txt', 'utf8')
  .then(data =&gt; console.log(data))
  .catch(err =&gt; console.error(err));
</code></pre>
<p>One line. Works on any standard Node.js callback-style function. And <code>fs.promises</code> (used earlier) is essentially the entire <code>fs</code> module pre-promisified — it's been available since Node 10 and is the modern default.</p>
<h2>Promise.all: Running Multiple Async Operations in Parallel</h2>
<p>This is one of the most useful patterns in real applications, and it has no clean equivalent in callback code.</p>
<p>Instead of chaining operations one after another, <code>Promise.all</code> runs multiple async operations simultaneously and waits for all of them:</p>
<pre><code class="language-javascript">const userPromise = db.findUser(userId);
const permsPromise = db.fetchPermissions(userId);
const prefsPromise = db.fetchPreferences(userId);

Promise.all([userPromise, permsPromise, prefsPromise])
  .then(([user, perms, prefs]) =&gt; {
    console.log(user.name, perms, prefs);
  })
  .catch(err =&gt; {
    // If ANY of the three fails, this runs
    console.error(err);
  });
</code></pre>
<p>Three DB queries running at the same time. All three results available together when they all finish. If any one fails, the <code>.catch()</code> fires.</p>
<p>Without Promises, achieving this with callbacks requires a manual counter or an async utility library. With Promises, it's one line.</p>
<p>Callbacks were the original Node.js async mechanism — simple, flexible, but painful to chain and error-handle at scale. They gave us "callback hell."</p>
<p>Promises replaced them with an object that represents a future value. <code>.then()</code> chains are flat and readable. <code>.catch()</code> handles errors from any step in the chain. <code>Promise.all</code> enables true parallelism in application code.</p>
<p>Understanding both is non-negotiable. You'll encounter callback-based APIs in older packages and existing codebases. You'll write and consume Promises in any modern Node.js project. And once you've internalized Promises, the final piece — <code>async/await</code> — clicks into place immediately.</p>
]]></content:encoded></item><item><title><![CDATA[The Node.js Event Loop Explained]]></title><description><![CDATA[Why does event loop exists
Node.js runs your JavaScript on a single thread. One thread means one thing executes at a time. In a traditional server, this would be catastrophic one slow database query a]]></description><link>https://blogs.satpal.cloud/the-node-js-event-loop-explained</link><guid isPermaLink="true">https://blogs.satpal.cloud/the-node-js-event-loop-explained</guid><category><![CDATA[Node.js]]></category><category><![CDATA[EventLoop]]></category><dc:creator><![CDATA[Satpalsinh Rana]]></dc:creator><pubDate>Sat, 09 May 2026 11:09:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/b7bce30d-3bfa-470a-918e-1f09f61be5cd.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Why does event loop exists</h2>
<p>Node.js runs your JavaScript on a single thread. One thread means one thing executes at a time. In a traditional server, this would be catastrophic one slow database query and every user would freeze.</p>
<p>Traditional servers solve this by throwing more threads at the problem. A hundred users? A hundred threads. But threads aren't free. Each one consumes memory (typically 1–8MB of stack space), and most of them spend the majority of their time doing nothing useful waiting. Waiting for a database to respond. Waiting for a file to load. Waiting for an API to return. All that waiting, and all that memory, and yet no actual work is happening.</p>
<p>Node.js takes a different position: instead of adding more threads, use the one thread <em>more intelligently</em>. Never let it wait. Whenever it would have to stop and wait for something, hand that something off and go do other work. Come back when the result is ready.</p>
<p>The mechanism that makes "come back when it's ready" possible is the event loop.</p>
<h2>Event Loop</h2>
<p>Here's the simplest mental model: the event loop is a task manager that runs in a continuous cycle.</p>
<p>It watches two things:</p>
<ol>
<li><p>The <strong>call stack</strong> — what's currently executing</p>
</li>
<li><p>The <strong>task queue</strong> — what's finished and ready to be processed next</p>
</li>
</ol>
<p>Its job is simple whenever the call stack is empty, take the next task from the queue and put it on the stack.</p>
<p>That's it. The whole mechanism boils down to that one rule. Everything else callbacks, promises, timers is just a way of getting tasks onto the queue at the right time.</p>
<h2>The Call Stack</h2>
<p>The call stack is where JavaScript execution happens. When you call a function, it gets pushed onto the stack. When it returns, it gets popped off.</p>
<pre><code class="language-javascript">function greet(name) {
  return `Hello, ${name}`;
}

function main() {
  const message = greet("Node.js");
  console.log(message);
}

main();
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/478e6350-338f-47ce-b4e8-e34ad3eb6985.gif" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">→ main() pushed onto stack
  → greet() pushed onto stack
  ← greet() returns, popped off stack
  → console.log() pushed onto stack
  ← console.log() completes, popped off stack
← main() returns, popped off stack
Stack is empty.
</code></pre>
<p><strong>JavaScript can only run one thing at a time.</strong> While a function is on the stack, nothing else runs. This is why blocking code is dangerous it keeps something on the stack for a long time, preventing anything else from ever getting a turn.</p>
<h2>The Task Queue</h2>
<p>When you kick off an async operation a database query, a file read, a timer Node.js registers a callback for it and immediately returns. Your synchronous code keeps running. The stack keeps moving.</p>
<p>Meanwhile, the I/O operation is happening elsewhere (more on this below). When it completes, its result and callback don't get shoved directly onto the call stack. Instead, they get placed into the <strong>task queue</strong> a waiting line.</p>
<p>The event loop watches this queue. The moment the call stack is empty, it picks up the next item from the queue and pushes it onto the stack. The callback runs. Gets popped off. The event loop checks for more items. The cycle continues.</p>
<pre><code class="language-javascript">console.log("first");

setTimeout(() =&gt; {
  console.log("third");  // callback queued, runs after stack clears
}, 0);

console.log("second");
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/a86091da-4ead-457e-b5c7-a5d5a7b3c97d.gif" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">first
second
third
</code></pre>
<p>Even with a 0ms timer, "third" prints last. The <code>setTimeout</code> callback goes to the task queue. The synchronous code — <code>console.log("second")</code> — stays on the stack and runs first. Only after the stack is completely empty does the event loop pull the callback from the queue.</p>
<p>This surprises developers the first time. The timer delay is not a promise of <em>when</em> the callback runs. It's a minimum time before it's <em>eligible</em> to run. The event loop decides the actual execution time.</p>
<h2>Timers vs I/O Callbacks</h2>
<p>Here's something most introductory articles skip: not all async callbacks are treated equally in the task queue.</p>
<p>Node.js actually has multiple queues with different priorities:</p>
<p><strong>Timers</strong> (<code>setTimeout</code>, <code>setInterval</code>) — checked first each cycle. A callback becomes eligible after the specified delay has passed, but runs at the start of the next loop tick once eligible.</p>
<p><strong>I/O callbacks</strong> — responses from file reads, network requests, database queries. These sit in a separate pool and are processed after timers.</p>
<p><code>setImmediate</code> — runs after I/O callbacks in the current cycle, before the next timer check. This is a uniquely Node.js feature with no browser equivalent.</p>
<p><code>process.nextTick</code> — this one is special. It runs <em>before</em> the event loop moves to the next phase, no matter what. Immediately after the current operation finishes, before any I/O or timers. Developers use it to defer work until the current call stack unwinds, but still within "this tick."</p>
<pre><code class="language-javascript">setTimeout(function fun1() {
  console.log("timer")
},0);

setImmediate(function fun2() {
  console.log("immediate")
});

process.nextTick(function fun3() {
  console.log("next tick")
});

console.log("synchronous");
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/427e2c65-9edf-4bba-903a-2538439d13b1.gif" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">synchronous
nextTick
timer (or immediate — order between these two can vary)
immediate (or timer)
</code></pre>
<p><code>process.nextTick</code> always fires before any I/O or timers, even before <code>setImmediate</code>. This makes it useful for ensuring something happens after the current operation but before any async work. Use it carefully stacking too many <code>nextTick</code> calls can starve the I/O queue.</p>
<h2>Delegating to Background Workers</h2>
<p>Here's the part the "single-threaded" framing obscures: when Node.js delegates I/O work, that work doesn't vanish into thin air. It goes to <strong>libuv</strong> — the C library underneath Node.js that provides the event loop and a worker thread pool.</p>
<p>When you call <code>fs.readFile()</code>, Node hands the actual disk read to libuv. Libuv's thread pool (4 threads by default) handles the operation. When it finishes, libuv places the callback on the event loop's I/O queue. The event loop picks it up and runs your callback on the JavaScript thread.</p>
<p>Your JavaScript never sees the worker threads. From your perspective, you called a function, moved on, and later your callback ran with the result. The multi-threading is invisible.</p>
<p>This is why Node.js can claim to be "single-threaded" while also doing actual parallel I/O work. The single thread is <em>your</em> thread the JavaScript execution context. The libuv thread pool is infrastructure, below the JS layer.</p>
<p>The developers who truly understand the event loop don't just write async code they write async code that keeps the loop running smoothly. That's the difference between a Node.js server that handles 10,000 concurrent connections and one that mysteriously crawls under load.</p>
<p>I’m currently deep-diving into the <strong>JavaScript</strong>, building projects and exploring the internals of the web. If you're on a similar journey or just love talking about JavaScript, let’s stay in touch!</p>
<ul>
<li><p><strong>Connect on LinkedIn:</strong> <a href="https://www.linkedin.com/in/satpalsinhrana"><strong>Satpalsinh's Profile</strong></a></p>
</li>
<li><p><strong>Follow my Blog:</strong> <a href="http://blogs.satpal.cloud"><strong>blogs.satpal.cloud</strong></a></p>
</li>
</ul>
<p><strong>Keep coding and keep building.</strong></p>
]]></content:encoded></item><item><title><![CDATA[Blocking vs Non-Blocking Code]]></title><description><![CDATA[Blocking
Who better know than us, what blocking means. Sad story...Whether it’s your ex-girlfriend or your Node.js server, being blocked fundamentally ruins everyone's day.
Symptoms of Blocking

Timer]]></description><link>https://blogs.satpal.cloud/blocking-vs-non-blocking-code</link><guid isPermaLink="true">https://blogs.satpal.cloud/blocking-vs-non-blocking-code</guid><category><![CDATA[Node.js]]></category><category><![CDATA[ChaiCode]]></category><dc:creator><![CDATA[Satpalsinh Rana]]></dc:creator><pubDate>Sat, 09 May 2026 06:29:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/9a3d7fa8-97d8-478a-960c-cf061759d258.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3>Blocking</h3>
<p>Who better know than us, what blocking means. Sad story...<br />Whether it’s your ex-girlfriend or your Node.js server, being blocked fundamentally ruins everyone's day.</p>
<p>Symptoms of Blocking</p>
<ul>
<li><p>Timer Freeze.</p>
</li>
<li><p>Callbacks waiting..</p>
</li>
</ul>
<h3>Non Blocking</h3>
<p>Opposite of blocking. It's smooth process.</p>
<h3>Example</h3>
<p>Blocking (synchronous)  </p>
<pre><code class="language-javascript">const fs = require('fs');

console.log('Before read');

const data = fs.readFileSync('./data.txt', 'utf8'); // ← thread stops here
console.log(data);

console.log('After read'); 
</code></pre>
<pre><code class="language-plaintext">Before read
[file contents]
After read
</code></pre>
<p>The entire thread pauses at <code>readFileSync</code>. If this file is on a slow disk, or it's a large file, your server is frozen for that entire duration. Every other user waiting on your server waits too.</p>
<p><strong>Non-blocking (asynchronous) file read:</strong></p>
<pre><code class="language-javascript">const fs = require('fs');

console.log('Before read');

fs.readFile('./data.txt', 'utf8', (err, data) =&gt; {
  if (err) throw err;
  console.log(data); // ← runs when the file is done reading
});

console.log('After read'); // ← runs IMMEDIATELY, doesn't wait
</code></pre>
<pre><code class="language-plaintext">Before read
After read
[file contents]
</code></pre>
<p>This confuses developers the first time they see it. "After read" prints <em>before</em> the file contents? Yes. Because the file read is happening in the background. The callback fires later, when the OS has finished reading. The thread kept running after registering the callback.</p>
<p><strong>This reordering of output is the most reliable indicator that code is truly non-blocking.</strong></p>
<h3>Why Blocking Slows Servers:</h3>
<p>Let's say your server handles a request that reads a 10ms file. Ten milliseconds sounds nothing. But under load, it compounds fast.</p>
<p><strong>With blocking code:</strong></p>
<pre><code class="language-plaintext">User A request arrives  → file read starts → [10ms frozen] → response sent
User B request arrives  → queued, waiting while A is frozen
User C request arrives  → queued, waiting while A is frozen
...
</code></pre>
<p>If 100 users hit this endpoint simultaneously and each file read takes 10ms, the last user waits 1000ms — 1 full second — not because their file read took that long, but because they're waiting for 99 people ahead of them to get their turn on a frozen thread.</p>
<p><strong>With non-blocking code:</strong></p>
<pre><code class="language-plaintext">User A request arrives → readFile registered → callback queued → thread free
User B request arrives → readFile registered → callback queued → thread free
User C request arrives → readFile registered → callback queued → thread free
...
All file reads happen in parallel at OS level
All callbacks fire roughly at t=10ms
All responses sent near-simultaneously
</code></pre>
<p>Same 100 users. Total wait time: ~10ms for everyone. Not 1000ms. The non-blocking version is 100x faster in this scenario — not because the disk ran faster, but because the thread stopped waiting.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/d907a5df-5a0c-4e22-9540-80189b7f4255.png" alt="" style="display:block;margin:0 auto" />

<h3>What "Async" Means in Practice</h3>
<p>You'll see "async" used interchangeably with "non-blocking" in the Node.js world. They're not quite identical, but in practice the distinction rarely matters for application code.</p>
<p>Node.js gives you three ways to write non-blocking code, and they've evolved over time:</p>
<p><strong>Callbacks (original Node.js style)</strong></p>
<pre><code class="language-javascript">fs.readFile('./file.txt', 'utf8', (err, data) =&gt; {
  if (err) {
    console.error(err);
    return;
  }
  console.log(data);
});
</code></pre>
<p><strong>Promises</strong></p>
<pre><code class="language-javascript">const fs = require('fs').promises;

fs.readFile('./file.txt', 'utf8')
  .then(data =&gt; console.log(data))
  .catch(err =&gt; console.error(err));
</code></pre>
<p><strong>Async/Await (modern Node.js)</strong></p>
<pre><code class="language-javascript">const fs = require('fs').promises;

async function readMyFile() {
  try {
    const data = await fs.readFile('./file.txt', 'utf8');
    console.log(data);
  } catch (err) {
    console.error(err);
  }
}

readMyFile();
</code></pre>
<h2>Summary</h2>
<p>Blocking code freezes your entire server. Non-blocking code keeps your server responsive even under load. This isn't just good practice in Node.js it's the foundational contract that makes the single-threaded model work.</p>
<p>The <code>Sync</code> functions exist. Use them only when you're not handling concurrent requests (scripts, startup, CLI tools). In a running server, they're almost always a bug waiting to manifest under load.</p>
<p>Async/await is the cleanest way to write non-blocking code today. Under the hood it's still callbacks and promises but the syntax keeps your code readable while the event loop stays unblocked.</p>
<p>Write non-blocking code, and Node.js rewards you with performance that surprises people who've only ever used thread-per-request servers.</p>
<p>I’m currently deep-diving into the <strong>JavaScript</strong>, building projects and exploring the internals of the web. If you're on a similar journey or just love talking about JavaScript, let’s stay in touch!</p>
<ul>
<li><p><strong>Connect on LinkedIn:</strong> <a href="https://www.linkedin.com/in/satpalsinhrana"><strong>Satpalsinh's Profile</strong></a></p>
</li>
<li><p><strong>Follow my Blog:</strong> <a href="http://blogs.satpal.cloud"><strong>blogs.satpal.cloud</strong></a></p>
</li>
</ul>
<p><strong>Keep coding and keep building.</strong></p>
]]></content:encoded></item><item><title><![CDATA[Is Node.js Really Single-Threaded?]]></title><description><![CDATA[When developers first hear Node.js is single-threaded, they usually have one of two reactions either they're confused, or they're skeptical.  
How can a single thread handle thousands of simultaneous ]]></description><link>https://blogs.satpal.cloud/is-node-js-really-single-threaded</link><guid isPermaLink="true">https://blogs.satpal.cloud/is-node-js-really-single-threaded</guid><category><![CDATA[Node.js]]></category><category><![CDATA[ChaiCode]]></category><dc:creator><![CDATA[Satpalsinh Rana]]></dc:creator><pubDate>Sat, 09 May 2026 06:11:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/53d6e69a-1333-455e-af1e-587c10858c07.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When developers first hear Node.js is single-threaded, they usually have one of two reactions either they're confused, or they're skeptical.  </p>
<p>How can a single thread handle thousands of simultaneous users?<br />That's a fair question and the answer changes the way you think about concurrent systems.</p>
<h3>What a Thread Actually Is ?</h3>
<p>Before we can talk about single-threaded, we need to be clear on what a thread is.</p>
<p>A <strong>process</strong> is a running program. When you start Node.js, your OS creates a process for it memory space, file handles, all of it. That process is isolated. Other processes can't mess with its memory directly.</p>
<p>A <strong>thread</strong> lives inside a process. It's a unit of execution a sequence of instructions the CPU can run. One process can have many threads, all sharing the same memory space, all potentially running at the same time on different CPU cores.</p>
<p>Traditional web servers like Apache create a new thread (or even a new process) per incoming request.  </p>
<p>One user connects → one thread. A hundred users → a hundred threads. That model is simple and intuitive.</p>
<p>Node.js says one thread. For everything.</p>
<p>That sounds like a weakness. Here's why it isn't at least not for most web applications.</p>
<h3>Event Loop</h3>
<p>The single thread in Node.js isn't doing what you think it's doing most of the time. It's not running your code nonstop. It's mostly checking.</p>
<p>The event loop runs in a continuous cycle. Each pass through the loop (called a "tick") looks like this:</p>
<ol>
<li><p>Are there any timers that have expired? Run their callbacks.</p>
</li>
<li><p>Are there any pending I/O callbacks ready? Run them.</p>
</li>
<li><p>Are there any <code>setImmediate</code> callbacks queued? Run them.</p>
</li>
<li><p>Any close events? Handle them.</p>
</li>
<li><p>Nothing ready? Check again.</p>
</li>
</ol>
<p>The entire secret of Node.js performance lives in step 5. When there's nothing ready, the thread doesn't spin-wait burning CPU. It goes into an efficient waiting state, and the OS wakes it up the moment something is ready.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/3be8758d-87c9-4028-91df-170472605c17.png" alt="" style="display:block;margin:0 auto" />

<p>This is called <strong>I/O multiplexing</strong> and Node.js gets it essentially for free by sitting on top of <strong>libuv</strong>, which uses <code>epoll</code> on Linux, <code>kqueue</code> on macOS, and <code>IOCP</code> on Windows under the hood.  </p>
<p>These are OS-level mechanisms specifically designed for efficient I/O monitoring.</p>
<h3>What Actually Happens When Multiple Requests Hit Node.js</h3>
<p>Let's walk through three simultaneous requests arriving at a Node.js server.</p>
<p><strong>Request A</strong> arrives. Your route handler fires. It calls <code>db.query(...)</code> with a callback. Node registers that callback and hands the DB work off to libuv. Your handler returns. Control goes back to the event loop.</p>
<p><em>Microseconds later</em>, <strong>Request B</strong> arrives. Same thing handler fires, calls an API, callback registered, handler returns. Event loop keeps spinning.</p>
<p><em>Immediately after</em>, <strong>Request C</strong> arrives. Maybe this one doesn't need I/O it just reads from an in-memory cache and returns a response. The handler runs to completion in a single tick. Response sent. Done.</p>
<p>Now the event loop keeps checking. Eventually, the DB responds for Request A. The callback fires. You format the data, call <code>res.send()</code>. Done. Then the API responds for Request B. Its callback fires. Response sent.</p>
<p>From the outside from the perspective of the three clients who connected all three requests were handled at the same time. From Node's perspective, there was always only one thing running at any given instant. But because the expensive work was delegated, the thread was almost never actually waiting.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/ab6b12f8-ef0c-4a6f-a002-4989d59f803c.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">Timeline (single thread):

t=0ms   Request A arrives → DB query fired → handler exits → event loop
t=1ms   Request B arrives → API call fired → handler exits → event loop
t=2ms   Request C arrives → cache lookup → response sent → event loop
t=45ms  DB responds → Request A callback → response sent
t=120ms API responds → Request B callback → response sent

One thread. Three requests handled. No waiting.
</code></pre>
<h3>Thread vs Process: One More Thing Worth Knowing</h3>
<p>Threads within a process share memory. This is efficient (no copying data) but risky one thread can corrupt another's memory. Debugging race conditions in multi-threaded apps is notoriously painful.</p>
<p>Processes have separate memory. Safer, but communicating between them requires explicit mechanisms (IPC, message passing, shared files).</p>
<p>Node.js sidesteps the thread safety problem entirely by using one JS thread. No shared mutable state between concurrent handlers. No race conditions in your JS code.</p>
<p>When you do want parallelism in Node.js (for CPU-heavy work), you use <strong>Worker Threads</strong> or the <strong>Cluster module</strong> (spawns multiple Node processes, each with their own event loop). These are explicit, opt-in parallelism.</p>
<h3>Why Node.js Scales So Well (The Actual Reason)</h3>
<p>I<strong>t has a very low per-connection cost.</strong></p>
<p>In a thread-per-request model, each connection holds a thread. Threads typically consume between 1MB and 8MB of stack memory by default. Ten thousand concurrent connections = 10–80 GB of memory just for stack space. Before you've done any actual work.</p>
<p>In Node.js, an open connection waiting for data is just an entry in the event loop — a file descriptor and a callback reference. A few hundred bytes. Ten thousand concurrent open connections might cost you 50MB total.</p>
<p>This is the real reason LinkedIn went from 30 servers to 3 with Node.js. It wasn't that Node's code ran faster. It's that each idle connection cost almost nothing, so one machine could hold far more of them.</p>
<p>The technical term is <strong>C10K problem</strong> handling ten thousand concurrent connections. This was a serious challenge in the early 2000s. Node.js's architecture basically solves it by default.</p>
<h3>Actual Limitation</h3>
<p><strong>If you block the event loop, everything stops.</strong></p>
<p>Not slows down. Stops. Every single client waiting on your server will be frozen until your blocking code finishes, because there's only one thread.</p>
<p>This can happen with:</p>
<ul>
<li><p>A <code>for</code> loop iterating over 10 million items</p>
</li>
<li><p>Synchronous file reads (<code>fs.readFileSync</code>) in a hot path</p>
</li>
<li><p>Heavy JSON parsing of a massive payload</p>
</li>
<li><p><code>crypto.pbkdf2Sync</code> with many iterations</p>
</li>
<li><p>Any CPU-intensive computation running to completion without yielding</p>
</li>
</ul>
<pre><code class="language-javascript">app.get('/danger', (req, res) =&gt; {
  let sum = 0;
  for (let i = 0; i &lt; 1_000_000_000; i++) {
    sum += i; // 1 billion iterations on the JS thread
  }
  res.send({ sum }); // every other user waited for this
});
</code></pre>
<p>In a multi-threaded server, this would only block one thread. In Node.js, it blocks everything.</p>
<p>The fix: offload CPU work to Worker Threads, or use <code>setImmediate</code>/<code>process.nextTick</code> to yield control back to the event loop between chunks of work. But the key lesson is: Node's single-threaded model rewards I/O-heavy workloads and punishes CPU-heavy ones.</p>
<p>Know this going in. Build accordingly.</p>
<h3>Moral of the Story</h3>
<p>Single-threaded doesn't mean limited. It means focused. Node.js made a deliberate bet: most web applications are I/O-bound, not CPU-bound. If that's true for your application and it usually is then a single well-managed thread with non-blocking I/O outperforms a pool of threads most of which are just waiting.</p>
<p>Understand the event loop. Respect the single thread. Don't block it with CPU work. That's the entire contract.</p>
<p>I’m currently deep-diving into the <strong>JavaScript</strong>, building projects and exploring the internals of the web. If you're on a similar journey or just love talking about JavaScript, let’s stay in touch!</p>
<ul>
<li><p><strong>Connect on LinkedIn:</strong> <a href="https://www.linkedin.com/in/satpalsinhrana"><strong>Satpalsinh's Profile</strong></a></p>
</li>
<li><p><strong>Follow my Blog:</strong> <a href="http://blogs.satpal.cloud"><strong>blogs.satpal.cloud</strong></a></p>
</li>
</ul>
<p><strong>Keep coding and keep building.</strong></p>
]]></content:encoded></item><item><title><![CDATA[NodeJs for building fast WebApp ]]></title><description><![CDATA[Everyone have heard Node.js is fast. But fewer people know why or what specifically makes it a different beast compared to traditional server runtimes.
In Nodejs there are two important things to note]]></description><link>https://blogs.satpal.cloud/fast-webapp</link><guid isPermaLink="true">https://blogs.satpal.cloud/fast-webapp</guid><category><![CDATA[Node.js]]></category><category><![CDATA[ChaiCode]]></category><dc:creator><![CDATA[Satpalsinh Rana]]></dc:creator><pubDate>Sat, 09 May 2026 05:53:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/4a463bd2-ce87-44d7-8ef2-d6a243abc620.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Everyone have heard Node.js is fast. But fewer people know why or what specifically makes it a different beast compared to traditional server runtimes.</p>
<p>In Nodejs there are two important things to note down.</p>
<ul>
<li><p>V8</p>
</li>
<li><p>Libuv</p>
</li>
</ul>
<p>Here V8 (Chrome's JS engine) handles JavaScript execution. But the thing that makes Node.js fast for I/O isn't V8 it's libuv, a C library that powers the event loop, thread pool, and async I/O. When Node reads a file or makes a network call, libuv handles it at the OS level while your JS thread stays free.</p>
<h2>What Nodejs offers</h2>
<h3><strong>Blocking vs non-blocking I/O</strong></h3>
<p>Traditional servers handle one request per thread. While a thread waits for a database result, it just sits there blocked, doing nothing, burning memory. Node.js flips this instead of waiting, it registers a callback and moves on to the next request. When the data is ready, it circles back.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/f3f4c5f7-a352-4530-a979-e8dabd748c46.png" alt="" style="display:block;margin:0 auto" />

<h3><strong>Event-driven architecture</strong></h3>
<p>Node.js is built around a simple idea: <strong>things happen, and you react to them.</strong> You don't sit and check "is the file read yet?" in a loop. You say "when the file is done, call this function" and walk away. That's the event-driven model.</p>
<p>Under the hood, the event loop runs in phases each responsible for a different kind of event. Timers fire in the timers phase. Completed I/O callbacks fire in the poll phase. <code>setImmediate()</code> runs in the check phase. Understanding this order stops a whole class of subtle bugs.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/5857b7b6-8138-4c95-bc9a-31a6e442bd81.png" alt="" style="display:block;margin:0 auto" />

<h3><strong>Single-threaded but not what you think</strong></h3>
<p>Single-threaded sounds like a weakness. It isn't. Node.js has <strong>one JS thread</strong>, but that thread is almost never the bottleneck if you understand JS properly or just follow my blogs.</p>
<p>Database queries, file reads, and HTTP calls don't run on your JS thread libuv offloads them to the OS or an internal thread pool. Your JS thread just dispatches work and handles results.</p>
<h3><strong>Concurrency vs parallelism</strong></h3>
<p><strong>Parallelism</strong> is two cooks working simultaneously on two burners. <strong>Concurrency</strong> is one cook managing two pots starting one, monitoring both, stirring each when needed. Node.js is the one cook. Traditional multi-threaded servers are the two cooks. For I/O-heavy work, the one skilled cook wins less overhead, less coordination, less memory per request in flight.</p>
<p>When you genuinely need parallelism heavy encryption, image processing, ML inference use <code>worker_threads</code>. Unlike the <code>cluster</code> module (which spawns whole processes), Worker Threads share memory via <code>SharedArrayBuffer</code>. Your main thread stays free. Most devs still don't reach for it.</p>
<h3>If you are building something on internet where to use Nodejs</h3>
<p>Remember one thing no technology is the right for everything. Use it where it shines.</p>
<ul>
<li><p><strong>REST APIs and GraphQL servers</strong></p>
</li>
<li><p><strong>Real-time apps like chat, live feeds, collaboration</strong></p>
</li>
<li><p><strong>Streaming data pipelines</strong></p>
</li>
<li><p><strong>Avoid for CPU-heavy computation</strong></p>
</li>
</ul>
<h3><strong>Real Companies Betting on Node.js</strong></h3>
<p>Some of the highest-traffic systems in the world run on Node.js:</p>
<ul>
<li><p>Netflix moved their frontend server layer to Node.js and cut startup time by over 70%. They serve over 200 million users. LinkedIn switched from Ruby on Rails to Node.js and went from running 30 servers down to 3 handling double the traffic.</p>
</li>
<li><p>Uber built their dispatch and notification systems on Node.js. The real-time nature of ride-hailing is a perfect fit for event-driven architecture.</p>
</li>
<li><p>PayPal found Node.js handled double the requests per second compared to their Java solution, with 35% lower response times.</p>
</li>
<li><p>Trello, Walmart, NASA, Medium all use Node.js in significant parts of their infrastructure. These aren't companies that chose Node.js because it was trendy.</p>
</li>
</ul>
<p>Here's something that doesn't show up in benchmarks: Node.js shares JavaScript between your frontend and backend. Your team writes one language. You can share validation logic, type definitions, utility functions between client and server.<br />This isn't a Node.js performance feature. But it's a team performance feature. In organizations running at scale, the reduction in context-switching developers not needing to flip between Python/Java on the server and JavaScript on the client is genuinely significant.</p>
<p>I hope you get to know something valuable from the article.</p>
<p>I’m currently deep-diving into the <strong>JavaScript</strong>, building projects and exploring the internals of the web. If you're on a similar journey or just love talking about JavaScript, let’s stay in touch!</p>
<ul>
<li><p><strong>Connect on LinkedIn:</strong> <a href="https://www.linkedin.com/in/satpalsinhrana"><strong>Satpalsinh's Profile</strong></a></p>
</li>
<li><p><strong>Follow my Blog:</strong> <a href="http://blogs.satpal.cloud"><strong>blogs.satpal.cloud</strong></a></p>
</li>
</ul>
<p><strong>Keep coding and keep building.</strong></p>
]]></content:encoded></item><item><title><![CDATA[NodeJS ]]></title><description><![CDATA[Why Did Node.js Even Need to Exist?
You already know JavaScript. You know it runs in the browser. The entire purpose was simple make web pages respond to user actions. But have you ever think why does]]></description><link>https://blogs.satpal.cloud/nodejs</link><guid isPermaLink="true">https://blogs.satpal.cloud/nodejs</guid><category><![CDATA[Node.js]]></category><dc:creator><![CDATA[Satpalsinh Rana]]></dc:creator><pubDate>Mon, 20 Apr 2026 16:31:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/c79a459b-12fc-418b-a0a9-3a38ad0d6c07.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Why Did Node.js Even Need to Exist?</h2>
<p>You already know JavaScript. You know it runs in the browser. The entire purpose was simple make web pages respond to user actions. But have you ever think why does it run in the browser at all?</p>
<p>Because something inside the browser is reading your JavaScript line by line and telling the computer what to do. That something is called a runtime engine. In Chrome, it's called V8. In Firefox, it's SpiderMonkey. Think of it as a translator JavaScript speaks, the engine listens, and the computer acts.</p>
<p>Now here's the problem. That translator only lived inside the browser. You couldn't take it outside. You couldn't run JavaScript on a server, talk to a database, read files on disk, or build an API. JavaScript was essentially trapped.</p>
<p><strong>Ryan Dahl</strong> looked at this in 2009 and said what if we break it out? He took V8 out of Chrome and wrapped it with something extra. That wrapper became Node.js.</p>
<h2>How Nodejs was build?</h2>
<p><strong>Ryan</strong> noticed that Google's V8 engine inside Chrome was fast, open-source, and not tied to the browser in any fundamental way. It was just a C++ library that could compile and execute JavaScript. So he pulled it out.</p>
<p>But V8 alone was only half the answer. He needed to give it hands. He wrapped V8 with a C library called <strong>libuv</strong>, which was built specifically to handle I/O operations file system calls, network connections, DNS lookups across different operating systems in a non-blocking way.</p>
<p>That combination is the entire foundation of Node.js.</p>
<h2>V8</h2>
<p>You don't need to understand V8 deeply to use Node.js. But a high-level picture helps.</p>
<p>V8 job is to take JavaScript code and turn it into something the CPU can actually. V8 reads your code, figures out what it's doing, and translates it into native machine code on the fly. This is called JIT(Just in time) compilation.</p>
<p>The result is that JavaScript runs fast compared to what anyone expected from a scripting language. V8 also handles memory management for you allocating it when you create objects, cleaning it up when you're done with them, through a process called garbage collection.</p>
<p>When Node.js runs your code, V8 is the one actually executing it. Node.js just sets the stage.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/402fffe2-9f89-4840-bd35-ec577f053589.png" alt="" style="display:block;margin:0 auto" />

<h2>Event Drive Architecture</h2>
<p>Let's use an analogy. Imagine a restaurant.</p>
<p>Traditional servers like PHP or Java with thread-per-request models work like a waiter who takes your order and then stands next to your table, doing absolutely nothing, until your food comes out of the kitchen. During that entire waiting time, that waiter is occupied. If 1,000 customers walk in, you need 1,000 waiters just standing around.</p>
<p>Node.js works like a smart waiter. They take your order, walk it to the kitchen, and immediately go take the next table's order. When the kitchen shouts "order up!", the waiter gets notified and delivers it. One waiter can handle 100 tables because they're never standing around waiting.</p>
<p>That's event-driven, non-blocking I/O. Instead of stopping everything while waiting for a database response or a file read, Node.js registers a callback and moves on. When the result is ready, it comes back via the event loop.</p>
<p>This is the reason Node.js can handle tens of thousands of concurrent connections on a single server process while traditional multi-threaded servers would be crushed under that load. Not because Node.js is faster at computation it's often not. But because it never idles.</p>
<p>Now here's how the Node.js runtime architecture actually fits together:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/a76a497a-4970-4426-b950-97a8f59b00e7.png" alt="" style="display:block;margin:0 auto" />

<h2>General use cases</h2>
<ul>
<li><p>REST APIs and GraphQL Backends</p>
</li>
<li><p>Streaming applications</p>
</li>
<li><p>Serverless functions</p>
</li>
<li><p>Internet of Things (IoT)</p>
</li>
</ul>
<p>I hope you get to know something valuable from the article.</p>
<p>I’m currently deep-diving into the <strong>JavaScript</strong>, building projects and exploring the internals of the web. If you're on a similar journey or just love talking about JavaScript, let’s stay in touch!</p>
<ul>
<li><p><strong>Connect on LinkedIn:</strong> <a href="https://www.linkedin.com/in/satpalsinhrana"><strong>Satpalsinh's Profile</strong></a></p>
</li>
<li><p><strong>Follow my Blog:</strong> <a href="http://blogs.satpal.cloud"><strong>blogs.satpal.cloud</strong></a></p>
</li>
</ul>
<p><strong>Keep coding and keep building.</strong></p>
]]></content:encoded></item><item><title><![CDATA[Array Flatten in JavaScript]]></title><description><![CDATA[What Exactly Are Nested Arrays?
A nested array (or a multi-dimensional array) is simply an array that contains other arrays as its elements.
Think of a standard array as a single-story egg carton. A n]]></description><link>https://blogs.satpal.cloud/array-flatten-in-javascript</link><guid isPermaLink="true">https://blogs.satpal.cloud/array-flatten-in-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[ChaiCode]]></category><category><![CDATA[Chaiaurcode]]></category><dc:creator><![CDATA[Satpalsinh Rana]]></dc:creator><pubDate>Thu, 26 Mar 2026 17:09:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/f25b597d-e56b-4c7a-b7ec-0e53942fe6de.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>What Exactly Are Nested Arrays?</h2>
<p>A nested array (or a multi-dimensional array) is simply an array that contains other arrays as its elements.</p>
<p>Think of a standard array as a single-story egg carton. A nested array is more like a shipping crate filled with smaller boxes, some of which might contain even smaller boxes.</p>
<p><strong>Example:</strong> <code>const nested = [1, [2, 3], [[4, 5], 6]];</code></p>
<p>In the example above, <code>1</code> is at the top level, but <code>4</code> and <code>5</code> are buried three levels deep.</p>
<h2>Why Bother Flattening?</h2>
<p>Flattening is the process of reducing the dimensionality of an array. We do this because:</p>
<ul>
<li><p><strong>Easier Iteration:</strong> It’s much simpler to run a single <code>.map()</code> or <code>.forEach()</code> on a flat list than to write recursive loops for every level.</p>
</li>
<li><p><strong>Data Consistency:</strong> Many UI components (like dropdowns or tables) expect a simple, linear array of items.</p>
</li>
<li><p><strong>Searchability:</strong> Finding a specific value is faster when you don't have to check every "sub-box."</p>
</li>
</ul>
<h2>Transformation</h2>
<p>When we "flatten," we are essentially taking every element from the inner arrays and pushing them into a new, single-level array while maintaining their original order.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/2f971932-454f-4e49-aa7e-3032577f7046.png" alt="" style="display:block;margin:0 auto" />

<h3>How to Flatten Arrays:</h3>
<h2><code>flat()</code></h2>
<p>Introduced in ES2019, the <code>.flat()</code> method is the gold standard. By default, it flattens one level deep, but you can pass a depth or use <code>Infinity</code> to go all the way.</p>
<pre><code class="language-javascript">const multidimensional = [1, [2, [3, [4]]]];

console.log(multidimensional.flat()); // [1, 2, [3, [4]]]

console.log(multidimensional.flat(Infinity)); // [1, 2, 3, 4]
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/ddb27ef8-5524-4391-afc6-c440c69a4b8d.png" alt="" style="display:block;margin:0 auto" />

<h2><code>reduce()</code> and <code>concat()</code></h2>
<p>Before <code>.flat()</code> existed, this was the go-to manual method. It helps you understand the <strong>logic</strong> of the transformation: "Take the accumulator, and merge it with the current item."</p>
<pre><code class="language-javascript">const nested = [1, [2, 3], [4]];
const flat = nested.reduce((acc, val) =&gt; acc.concat(val), []);
</code></pre>
<h2><code>toString()</code> and <code>split()</code></h2>
<p>If your array only contains numbers or strings, you can convert the whole thing to a string (which removes brackets) and then split it back.</p>
<p>Note: Use this with caution, as it turns everything into strings!</p>
<p>When you see a nested structure, just ask yourself about the <strong>depth</strong>.</p>
<ul>
<li><p>Is it always one level deep? Use <code>[].concat(...arr)</code>.</p>
</li>
<li><p>Is the depth unknown? Use <code>.flat(Infinity)</code>.</p>
</li>
<li><p>Are you on an older environment (like legacy IE)? You'll need a recursive polyfill.</p>
</li>
</ul>
<p>Flattening isn't just about making arrays shorter; it’s about making your data <strong>usable</strong>.</p>
]]></content:encoded></item><item><title><![CDATA[Error Handling in JavaScript]]></title><description><![CDATA[Every program makes assumptions. It assumes the network is available. It assumes the user gave you a valid input. It assumes the file exists. It assumes the API response has the shape you expect.
Most]]></description><link>https://blogs.satpal.cloud/error-handling-in-javascript</link><guid isPermaLink="true">https://blogs.satpal.cloud/error-handling-in-javascript</guid><category><![CDATA[error handling]]></category><category><![CDATA[ChaiCode]]></category><category><![CDATA[Chaiaurcode]]></category><dc:creator><![CDATA[Satpalsinh Rana]]></dc:creator><pubDate>Thu, 26 Mar 2026 16:55:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/80978952-1e64-46ca-aefd-e1b169ace0ce.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Every program makes assumptions. It assumes the network is available. It assumes the user gave you a valid input. It assumes the file exists. It assumes the API response has the shape you expect.</p>
<p>Most of the time those assumptions hold. Then they don't and what happens next is entirely up to you.</p>
<p>JavaScript gives you a system for managing failures without letting them crash the whole program. Understanding it isn't just about catching errors. It's about writing code that fails gracefully code that tells you exactly what went wrong, cleans up after itself, and gives the user something useful instead of a blank screen or a frozen UI.</p>
<h2>What errors actually are in JavaScript</h2>
<p>When JavaScript encounters something it can't handle dividing by something illegal, calling a method on <code>undefined</code>, trying to parse malformed JSON it creates an <code>Error</code> object and throws it. This throw unwinds the call stack, skipping everything below it, until something catches it or it reaches the top level and crashes your program.</p>
<pre><code class="language-javascript">const user = null;
console.log(user.name); // TypeError: Cannot read properties of null
</code></pre>
<p>That <code>TypeError</code> is a real object. It has a <code>message</code> (what went wrong), a <code>name</code> (the type of error), and a <code>stack</code> (the trace of function calls that led here). JavaScript creates it, throws it, and your program stops unless something is listening for it.</p>
<p>JavaScript has several built-in error types:</p>
<ul>
<li><p><code>TypeError</code> (wrong type)</p>
</li>
<li><p><code>ReferenceError</code> (variable doesn't exist)</p>
</li>
<li><p><code>SyntaxError</code> (invalid code)</p>
</li>
<li><p><code>RangeError</code> (value out of bounds).</p>
</li>
</ul>
<p>They all inherit from the base <code>Error</code> class.</p>
<h2>The <code>try/catch</code> block</h2>
<p><code>try/catch</code> lets you put risky code in a guarded zone. If anything throws inside <code>try</code>, execution jumps immediately to <code>catch</code> and you decide what to do with the error instead of letting it crash your program.</p>
<pre><code class="language-javascript">try {
  const data = JSON.parse("this is not valid json");
  console.log(data);
} catch (error) {
  console.error("Failed to parse:", error.message);
}

// Failed to parse: Unexpected token 'h', "this is n"... is not valid JSON
</code></pre>
<p>Without <code>try/catch</code>, that <code>JSON.parse</code> throws a <code>SyntaxError</code> and everything stops. With it, you catch the error, log it clearly, and your program keeps running.</p>
<p>The <code>error</code> object passed to <code>catch</code> is whatever was thrown. It has two properties you'll use constantly:</p>
<pre><code class="language-javascript">try {
  undeclaredVariable;
} catch (error) {
  console.log(error.name);    // "ReferenceError"
  console.log(error.message); // "undeclaredVariable is not defined"
}
</code></pre>
<h2>The <code>finally</code> block</h2>
<p><code>finally</code> is a block that runs no matter what whether the <code>try</code> succeeded, whether the <code>catch</code> triggered, whether an error was re-thrown. It always runs.</p>
<pre><code class="language-javascript">function loadData() {
  showSpinner();

  try {
    const result = fetchSomething();
    display(result);
  } catch (error) {
    showErrorMessage(error.message);
  } finally {
    hideSpinner(); // always runs — success or failure
  }
}
</code></pre>
<p><code>hideSpinner()</code> runs whether <code>fetchSomething</code> succeeded or crashed. Without <code>finally</code>, you'd have to call <code>hideSpinner()</code> in both the <code>try</code> and the <code>catch</code>, duplicating cleanup logic. <code>finally</code> exists precisely for this: teardown, cleanup, resource release anything that must happen regardless of outcome.</p>
<p>Here's the full execution order laid out clearly:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/86b2e517-4fcb-49d2-b925-896d3f8b052f.png" alt="" style="display:block;margin:0 auto" />

<h2>Throwing custom errors</h2>
<p>JavaScript lets you throw anything but throwing a proper <code>Error</code> object (or a subclass of it) is best practice because it gives you a stack trace and a message.</p>
<pre><code class="language-javascript">function divide(a, b) {
  if (b === 0) {
    throw new Error("Cannot divide by zero");
  }
  return a / b;
}

try {
  const result = divide(10, 0);
} catch (error) {
  console.error(error.message); // "Cannot divide by zero"
}
</code></pre>
<p>You're not waiting for JavaScript to fail you're proactively saying "this situation is invalid" and throwing your own error. The caller's <code>catch</code> block handles it just like any built-in error.</p>
<p>For larger applications, creating custom error classes makes your error handling more precise you can catch specific error types and respond differently:</p>
<pre><code class="language-javascript">class ValidationError extends Error {
  constructor(message, field) {
    super(message);
    this.name = "ValidationError";
    this.field = field;
  }
}

class NetworkError extends Error {
  constructor(message, statusCode) {
    super(message);
    this.name = "NetworkError";
    this.statusCode = statusCode;
  }
}

function processForm(data) {
  if (!data.email.includes("@")) {
    throw new ValidationError("Invalid email address", "email");
  }
}

try {
  processForm({ email: "notanemail" });
} catch (error) {
  if (error instanceof ValidationError) {
    console.log(`Validation failed on field: ${error.field}`);
    highlightField(error.field);
  } else if (error instanceof NetworkError) {
    console.log(`Network failed with status: ${error.statusCode}`);
    showRetryButton();
  } else {
    console.error("Unexpected error:", error);
  }
}
</code></pre>
<p><code>instanceof</code> lets you branch on error type different failures get different responses instead of one generic "something went wrong" message.</p>
<h2>Error handling with async/await</h2>
<p><code>try/catch</code> works exactly the same way with <code>async/await</code>. Rejected promises become catchable errors:</p>
<pre><code class="language-javascript">async function loadUserData(id) {
  try {
    const response = await fetch(`/api/users/${id}`);

    if (!response.ok) {
      throw new NetworkError("Request failed", response.status);
    }

    const user = await response.json();
    return user;
  } catch (error) {
    if (error instanceof NetworkError) {
      console.error(`HTTP \({error.statusCode}: \){error.message}`);
    } else {
      console.error("Unexpected error:", error.message);
    }
    return null;
  } finally {
    hideLoadingIndicator();
  }
}
</code></pre>
<p>Same underlying problem. Completely different user experience. Error handling is how you translate a technical failure into a useful human message.</p>
<p>A pattern worth building into any serious application:</p>
<pre><code class="language-javascript">async function safeLoadDashboard() {
  try {
    const [user, stats, notifications] = await Promise.all([
      fetchUser(),
      fetchStats(),
      fetchNotifications()
    ]);

    renderDashboard(user, stats, notifications);
  } catch (error) {
    console.error("Dashboard load failed:", error);
    renderErrorState("Unable to load dashboard. Please refresh.");
  } finally {
    hideGlobalSpinner();
  }
}
</code></pre>
<p>If any of the three fetches fail, <code>catch</code> handles it.</p>
]]></content:encoded></item><item><title><![CDATA[Async/Await in JavaScript]]></title><description><![CDATA[You've met promises. You understand .then(). You've chained a few calls together and it mostly worked. But then you needed to do three async things in sequence, and you ended up with something like th]]></description><link>https://blogs.satpal.cloud/async-await-in-javascript</link><guid isPermaLink="true">https://blogs.satpal.cloud/async-await-in-javascript</guid><category><![CDATA[asynchronous]]></category><category><![CDATA[async/await]]></category><category><![CDATA[ChaiCode]]></category><category><![CDATA[Chaiaurcode]]></category><dc:creator><![CDATA[Satpalsinh Rana]]></dc:creator><pubDate>Thu, 26 Mar 2026 16:53:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/0ea37423-9879-4fab-9987-4a3a14a2f201.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You've met promises. You understand <code>.then()</code>. You've chained a few calls together and it mostly worked. But then you needed to do three async things in sequence, and you ended up with something like this:</p>
<pre><code class="language-javascript">getUser(userId)
  .then(user =&gt; {
    return getOrders(user.id);
  })
  .then(orders =&gt; {
    return getProduct(orders[0].productId);
  })
  .then(product =&gt; {
    console.log(product.name);
  })
  .catch(err =&gt; {
    console.error(err);
  });
</code></pre>
<p>It works. But it reads sideways. Each <code>.then()</code> is a new indentation, a new callback, a new mental context to hold. You can't easily share variables between steps without hoisting them outside the chain. Error handling applies to the whole chain but it's tacked on at the end, invisible until something breaks.</p>
<p><code>async/await</code> was introduced in ES2017 to fix exactly this. Not by replacing promises by giving you a way to write promise-based code that looks and reads like regular synchronous code.</p>
<h2>Syntactic sugar over promises</h2>
<p>The first thing to understand is that <code>async/await</code> is not a new async system. It's a new <em>syntax</em> for working with promises. Under the hood, every <code>async</code> function returns a promise. Every <code>await</code> pauses execution and waits for a promise to resolve. No new engine magic just a cleaner way to write what you were already doing.</p>
<p>Think of it this way. Promises gave you a contract: "this will eventually have a value." <code>async/await</code> gives you a way to write code as if that value is already there, and JavaScript handles the waiting behind the scenes.</p>
<h2>The <code>async</code> keyword</h2>
<p>Putting <code>async</code> before a function declaration does one thing: it makes that function always return a promise. Even if you return a plain value, JavaScript automatically wraps it in a resolved promise.</p>
<pre><code class="language-javascript">async function greet() {
  return "Hello!";
}

greet().then(msg =&gt; console.log(msg)); // "Hello!"
</code></pre>
<p>You returned a string. But because the function is <code>async</code>, the caller receives a promise that resolves to that string. That's the contract.</p>
<p>You can use <code>async</code> with any function style:</p>
<pre><code class="language-javascript">// function declaration
async function fetchData() { ... }

// arrow function
const fetchData = async () =&gt; { ... }

// method in an object
const api = {
  async getUser() { ... }
};
</code></pre>
<h2>The <code>await</code> keyword</h2>
<p><code>await</code> can only live inside an <code>async</code> function. It pauses that function's execution until the promise it's waiting on resolves then hands you the resolved value directly.</p>
<pre><code class="language-javascript">async function loadUser() {
  const user = await getUser(1); // pauses here until resolved
  console.log(user.name);        // then continues
}
</code></pre>
<p>Without <code>await</code>, <code>getUser(1)</code> returns a promise object not the user. With <code>await</code>, you get the user directly, as if the function was synchronous. The pause is real but it's non-blocking: while this function is waiting, JavaScript keeps running everything else.</p>
<p>Here's what that promise chain from earlier looks like rewritten with <code>async/await</code>:</p>
<pre><code class="language-javascript">async function loadProductFromUser(userId) {
  const user    = await getUser(userId);
  const orders  = await getOrders(user.id);
  const product = await getProduct(orders[0].productId);

  console.log(product.name);
}
</code></pre>
<p>Top to bottom. Left to right. Each line waits for the previous one before moving on. No callbacks. No indentation staircase. It reads like a recipe: get the user, get their orders, get the first product, show its name.</p>
<p>Here's the execution flow when you call an <code>async</code> function:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/0bfb2d33-c56f-4e7a-933b-12c20a99491b.png" alt="" style="display:block;margin:0 auto" />]]></content:encoded></item><item><title><![CDATA[JavaScript Promises Explained for Beginners]]></title><description><![CDATA[What problem do promises solve?
JavaScript is single-threaded. It runs one piece of code at a time, which means when you perform a slow operation, like fetching data from a server, reading a file, or ]]></description><link>https://blogs.satpal.cloud/javascript-promises-explained-for-beginners</link><guid isPermaLink="true">https://blogs.satpal.cloud/javascript-promises-explained-for-beginners</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[promises]]></category><category><![CDATA[ChaiCode]]></category><category><![CDATA[Chaiaurcode]]></category><dc:creator><![CDATA[Satpalsinh Rana]]></dc:creator><pubDate>Thu, 26 Mar 2026 16:26:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/f901a37b-c130-46de-9071-0ff0500e4c1d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>What problem do promises solve?</h2>
<p>JavaScript is single-threaded. It runs one piece of code at a time, which means when you perform a slow operation, like fetching data from a server, reading a file, or waiting for a timer.</p>
<p>The entire thread can't afford to stop and wait. Instead, JavaScript uses an event-driven, asynchronous model: kick off the work, continue with other things, and handle the result when it's ready.</p>
<p>The earliest pattern for this was the <strong>callback</strong> you pass a function to another function, and that function calls yours back when the work completes. This works, but it breaks down fast. Imagine fetching a user, then fetching their posts, then fetching comments on each post. You end up nesting callbacks inside callbacks inside callbacks code that fans rightward across the screen, where error handling is duplicated at every level and the logical sequence of operations is buried in indentation. Developers called this callback hell.</p>
<p>Promises were introduced to solve this. A promise represents a value that isn't available <em>yet</em>, but will be in the future or won't arrive at all because something went wrong. Instead of passing callbacks into every function, you work with an object that carries the result of an asynchronous operation, with a clean, chainable API for handling success and failure.</p>
<h2>Promise states</h2>
<p>Every promise lives in exactly one of three states at any given moment:</p>
<p><strong>Pending</strong>: The operation is in progress. No result yet. This is the starting state.</p>
<p><strong>Fulfilled</strong>: The operation completed successfully. The promise now holds the resolved value.</p>
<p><strong>Rejected:</strong> The operation failed. The promise now holds a reason, typically an <code>Error</code> object explaining what went wrong.</p>
<p>The key rule: once a promise transitions out of pending, it never changes again. A fulfilled promise stays fulfilled forever. A rejected promise stays rejected. This predictability is one of the things that makes promises much easier to reason about than raw callbacks.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/fb72eabc-c603-4247-b60e-b84bb4d5917a.png" alt="" style="display:block;margin:0 auto" />

<h2>Creating a promise</h2>
<p>You create a promise by calling the <code>Promise</code> constructor and passing it an <strong>executor</strong>, a function that receives two callbacks: <code>resolve</code> and <code>reject</code>. You call one of them when the async work finishes.</p>
<pre><code class="language-javascript">const fetchUser = new Promise((resolve, reject) =&gt; {
  setTimeout(() =&gt; {
    const success = true; // pretend this comes from a network call

    if (success) {
      resolve({ id: 1, name: 'Priya' }); // fulfills the promise
    } else {
      reject(new Error('User not found')); // rejects the promise
    }
  }, 1000);
});
</code></pre>
<p>The executor runs immediately when <code>new Promise(...)</code> is called. The resolve and reject callbacks settle the promise and trigger any handlers that have been attached.</p>
<h2>Handling success and failure</h2>
<p>Once you have a promise, you react to its outcome using <code>.then()</code>, <code>.catch()</code>, and <code>.finally()</code>:</p>
<pre><code class="language-javascript">fetchUser
  .then((user) =&gt; {
    console.log('Got user:', user.name); // runs if resolved
  })
  .catch((error) =&gt; {
    console.error('Failed:', error.message); // runs if rejected
  })
  .finally(() =&gt; {
    console.log('Done loading'); // always runs
  });
</code></pre>
<p><code>.then()</code> receives the resolved value. <code>.catch()</code> receives the rejection reason. <code>.finally()</code> receives nothing.</p>
<p>It's purely for cleanup (hiding a loading spinner, closing a connection). A critical point: <code>.finally()</code> <strong>doesn't consume the promise value</strong>. Whatever the promise settled with flows through <code>.finally()</code> unchanged to any subsequent handler.</p>
<h2>Callbacks vs promises</h2>
<p>Let's look at a concrete comparison. Three sequential async operations: load a user, then load their orders, then calculate their total spend.</p>
<pre><code class="language-javascript">loadUser(userId, function(err, user) {
  if (err) return handleError(err);
  loadOrders(user.id, function(err, orders) {
    if (err) return handleError(err);
    calculateSpend(orders, function(err, total) {
      if (err) return handleError(err);
      console.log('Total spend:', total);
    });
  });
});
</code></pre>
<p><strong>With promises:</strong></p>
<pre><code class="language-javascript">loadUser(userId)
  .then((user) =&gt; loadOrders(user.id))
  .then((orders) =&gt; calculateSpend(orders))
  .then((total) =&gt; console.log('Total spend:', total))
  .catch(handleError);
</code></pre>
<p>The logic is identical. But the promise version reads like a linear sequence of steps because it is one. Error handling is consolidated in a single <code>.catch()</code> at the end rather than duplicated at every level.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/d8787c3c-4730-491f-8b8c-4a0bab9e1705.png" alt="" style="display:block;margin:0 auto" />

<h2>Promise chaining</h2>
<p>Promise chaining is possible because <code>.then()</code> always returns a new promise. Whatever value you <code>return</code> from inside a <code>.then()</code> callback becomes the resolved value of that new promise, which the next <code>.then()</code> in the chain receives.</p>
<pre><code class="language-javascript">fetchUser(1)
  .then((user) =&gt; {
    return fetchPostsByUser(user.id); // returns another promise
  })
  .then((posts) =&gt; {
    return posts.filter((p) =&gt; p.published); // returns a plain array
  })
  .then((publishedPosts) =&gt; {
    console.log(publishedPosts.length, 'published posts');
  })
  .catch((err) =&gt; {
    // any rejection in the chain above lands here
    console.error('Something went wrong:', err.message);
  });
</code></pre>
<p>The chain automatically unwraps promises: if you return a promise from inside <code>.then()</code>, the next <code>.then()</code> waits for that inner promise to settle before it fires. If you return a plain value, it's wrapped into a resolved promise automatically. This is the mechanism that makes chaining work seamlessly for both sync and async return values.</p>
<h2>A note on <code>async/await</code></h2>
<p>Modern JavaScript introduced <code>async/await</code> as syntax sugar built directly on top of promises. An <code>async</code> function always returns a promise, and <code>await</code> pauses execution inside that function until a promise settles without blocking the thread. It makes promise-based code look synchronous:</p>
<pre><code class="language-javascript">async function loadDashboard(userId) {
  try {
    const user = await fetchUser(userId);
    const orders = await fetchOrders(user.id);
    const total = await calculateSpend(orders);
    console.log('Total spend:', total);
  } catch (err) {
    console.error('Failed:', err.message);
  }
}
</code></pre>
<p>This is the same sequence as the promise chain above, just written differently. Understanding promises deeply states, <code>.then()</code>, <code>.catch()</code>, chaining is essential before <code>async/await</code> makes sense, because under the hood, that's exactly what it's doing.</p>
]]></content:encoded></item><item><title><![CDATA[String Polyfills in JavaScript]]></title><description><![CDATA[What are string methods?
In JavaScript, strings come with a powerful set of built-in methods functions attached to every string value that let you search, transform, slice, and inspect text. When you ]]></description><link>https://blogs.satpal.cloud/string-polyfills-in-javascript</link><guid isPermaLink="true">https://blogs.satpal.cloud/string-polyfills-in-javascript</guid><category><![CDATA[polyfills]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[ChaiCode]]></category><category><![CDATA[Chaiaurcode]]></category><dc:creator><![CDATA[Satpalsinh Rana]]></dc:creator><pubDate>Thu, 26 Mar 2026 16:25:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/91df0725-22aa-4186-a7e8-a7e4c9442e65.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>What are string methods?</h2>
<p>In JavaScript, strings come with a powerful set of built-in methods functions attached to every string value that let you search, transform, slice, and inspect text. When you call <code>"hello".toUpperCase()</code>, you're using a method that JavaScript's engine provides automatically. These aren't magic; they're functions defined on <code>String.prototype</code>, the shared blueprint that every string inherits from.</p>
<p>The key insight for interview preparation is this: knowing what a method does isn't enough. Interviewers want to know how it works and whether you could rebuild it from scratch. That's where polyfills come in.</p>
<h2>Why developers write polyfills</h2>
<p>A polyfill is a piece of code that implements a feature that the current runtime doesn't support or that you're implementing yourself to demonstrate understanding. When a new string method lands in the JavaScript specification, older browsers don't have it. Developers write polyfills to bridge that gap, attaching the implementation directly to <code>String.prototype</code> before the browser's built-in version would run.</p>
<p>But in interviews, polyfills serve a different purpose. They force you to reason about the logic behind familiar tools. Can you write <code>trim()</code> without calling <code>trim()</code>? Can you implement <code>includes()</code> using only index-based access? These questions reveal how deeply you understand strings as sequences of characters.</p>
<p>Here's how the string processing model works under the hood:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/f69eaa1a-2166-4df1-8ff5-2e5970c4abfe.png" alt="" style="display:block;margin:0 auto" />

<p>One important detail the diagram highlights: strings in JavaScript are <strong>immutable</strong>. No string method ever modifies the original string.</p>
<h2>Implementing simple string utilities as polyfills</h2>
<p>Before writing a polyfill, always check if the method already exists. This prevents overwriting the native implementation in environments that support it.</p>
<pre><code class="language-javascript">if (!String.prototype.customTrim) {
  String.prototype.customTrim = function () {
    // `this` refers to the string value the method is called on
    let start = 0;
    let end = this.length - 1;

    while (start &lt;= end &amp;&amp; this[start] === ' ') start++;
    while (end &gt;= start &amp;&amp; this[end] === ' ') end--;

    return this.slice(start, end + 1);
  };
}
</code></pre>
<p>The logic here is a two-pointer approach.</p>
<p>Advance from the left until you hit a non-space character, retreat from the right until you hit a non-space character, then slice out the middle. This is exactly the kind of thinking interviews test: can you express a simple operation in terms of indices and comparisons?</p>
<p>Here's how the polyfill checking behavior works visually:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6950d1ca85602739c40abd67/c056b850-f3a8-4ce9-8183-0d3b01a966be.png" alt="" style="display:block;margin:0 auto" />

<h2>Common interview string methods to implement</h2>
<h3><code>includes(searchStr)</code></h3>
<p>The built-in method checks whether a substring exists anywhere in the string, returning <code>true</code> or <code>false</code>. The polyfill uses a sliding window: at every position, compare the next <code>searchStr.length</code> characters against the target.</p>
<pre><code class="language-javascript">String.prototype.myIncludes = function (searchStr) {
  const str = String(this);
  const search = String(searchStr);

  if (search.length === 0) return true;
  if (search.length &gt; str.length) return false;

  for (let i = 0; i &lt;= str.length - search.length; i++) {
    if (str.slice(i, i + search.length) === search) return true;
  }
  return false;
};
</code></pre>
<p>Note the edge cases: an empty search string always returns <code>true</code> (this matches the spec), and a search string longer than the source immediately returns <code>false</code>.</p>
<h3><code>repeat(count)</code></h3>
<p>This builds a new string by concatenating the original <code>count</code> times.</p>
<pre><code class="language-javascript">String.prototype.myRepeat = function (count) {
  const n = Math.floor(count);
  if (n &lt; 0 || n === Infinity) throw new RangeError('Invalid count value');
  let result = '';
  for (let i = 0; i &lt; n; i++) result += this;
  return result;
};
</code></pre>
<h3><code>startsWith(prefix)</code> and <code>endsWith(suffix)</code></h3>
<p>These are slice comparisons at fixed positions:</p>
<pre><code class="language-javascript">String.prototype.myStartsWith = function (prefix) {
  return this.slice(0, prefix.length) === prefix;
};

String.prototype.myEndsWith = function (suffix) {
  if (suffix.length === 0) return true;
  return this.slice(-suffix.length) === suffix;
};
</code></pre>
<h3><code>padStart(targetLength, padStr)</code> and <code>padEnd()</code></h3>
<p>Padding methods fill the string until it reaches a desired length:</p>
<pre><code class="language-javascript">String.prototype.myPadStart = function (targetLength, padStr = ' ') {
  const str = String(this);
  if (str.length &gt;= targetLength) return str;
  const padNeeded = targetLength - str.length;
  let padding = '';
  while (padding.length &lt; padNeeded) padding += padStr;
  return padding.slice(0, padNeeded) + str;
};
</code></pre>
]]></content:encoded></item></channel></rss>